我正在一個網站上工作,我需要能夠將4000x6000分割成4個部分(其中包括許多其他任務),並且我需要儘可能快地爲多個用戶。並行運行多個圖像操作導致OutOfMemory異常
我這樣做當前的代碼
var bitmaps = new RenderTargetBitmap[elements.Length];
using (var stream = blobService.Stream(key))
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = stream;
bi.EndInit();
for (var i = 0; i < elements.Length; i++)
{
var element = elements[i];
TransformGroup transformGroup = new TransformGroup();
TranslateTransform translateTransform = new TranslateTransform();
translateTransform.X = -element.Left;
translateTransform.Y = -element.Top;
transformGroup.Children.Add(translateTransform);
DrawingVisual vis = new DrawingVisual();
DrawingContext cont = vis.RenderOpen();
cont.PushTransform(transformGroup);
cont.DrawImage(bi, new Rect(new Size(bi.PixelWidth, bi.PixelHeight)));
cont.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(element.Width, element.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(vis);
bitmaps[i] = rtb;
}
}
for (var i = 0; i < bitmaps.Length; i++)
{
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmaps[i]));
encoder.Save(ms);
var regionKey = WebPath.Variant(key, elements[i].Id);
saveBlobService.Save("image/png", regionKey, ms);
}
}
我運行它採取的工作掀起了隊列多個線程。我發現如果這部分代碼一次被4個線程命中,我會得到一個OutOfMemory異常。我可以通過將上面的所有代碼包裝在lock(obj)
中來阻止這種情況的發生,但這並不理想。我試過包裝第一個使用塊(從磁盤讀取文件並拆分),但仍然出現內存不足異常(這部分代碼執行得相當快)。
- 我這個正常考慮這個應該佔用的內存量嗎?
- 我可以做什麼優化?
- 我可以增加可用內存嗎?
UPDATE:
我的新代碼,每Moozhe的幫助
public static void GenerateRegions(this IBlobService blobService, string key, Element[] elements)
{
using (var stream = blobService.Stream(key))
{
foreach (var element in elements)
{
stream.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.SourceRect = new Int32Rect(element.Left, element.Top, element.Width, element.Height);
bi.StreamSource = stream;
bi.EndInit();
DrawingVisual vis = new DrawingVisual();
DrawingContext cont = vis.RenderOpen();
cont.DrawImage(bi, new Rect(new Size(element.Width, element.Height)));
cont.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(element.Width, element.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(vis);
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(ms);
var regionKey = WebPath.Variant(key, element.Id);
blobService.Save("image/png", regionKey, ms);
}
}
}
}
您的服務器上有多少RAM?也許重試和隊列機制(例如排隊請求)可以在這裏幫助。 – ashes999
@ ashes999現在通過iis express在我的本地機器上運行,我的機器有12gigs – Tom
您是否嘗試編寫一些測試代碼,在您的計算機上加載10個或更多圖像以查看加載圖像是否導致問題? – Ani