WPF应用程序中的内存不足异常

时间:2013-09-11 15:51:21

标签: c# .net wpf memory-management out-of-memory

我正在创建一个应用程序,我从相机获取实时图像并尝试将其置于WPF的图像控制上。但过了一段时间后,它将开始抛出内存异常。

以下是代码:

try
{
    imgControl.Dispatcher.Invoke(DispatcherPriority.Normal,
    (Action)(() =>
    {
        using (MemoryStream memory = new MemoryStream())
        {
            lastImage.Save(memory, ImageFormat.Png);
            memory.Position = 0;
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memory;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();

            ImageSource imageSource = bitmapImage;
            imgControl.Source = imageSource;
        }
    }));
}
catch (Exception ex)
{
    //Exception handling
}

这是堆栈跟踪:

   at System.Windows.Media.Composition.DUCE.Channel.SyncFlush()
   at System.Windows.Interop.HwndTarget.UpdateWindowSettings(Boolean enableRenderTarget, Nullable`1 channelSet)
   at System.Windows.Interop.HwndTarget.UpdateWindowPos(IntPtr lParam)
   at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

有没有办法可以减少内存消耗并找到解决这种内存不足异常的方法?

3 个答案:

答案 0 :(得分:0)

我建议您患有大型物体堆(LOH)碎片。有没有办法可以将图像尺寸减小到85K字节以下,这样它们就不会达到LOH?

答案 1 :(得分:0)

如果您使用的是.NET 4.5.1,则可以执行on-demand LOH compaction

答案 2 :(得分:0)

我确实面临同样的情况,现在我必须用另一个完成这个,我会分享它。

这里我发布了在列表视图项目中为缩略图视图添加图像。同样,通过更改图像的宽度和高度,您可以通过bitmapsource对象的返回值获得所需的内容。

第1步

导入DLL文件文件:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

第2步

/// <summary>
/// Gets the thumnail of the source image.
/// </summary>
/// <returns></returns>

private BitmapSource GetThumbnail(string fileName)
{
    BitmapSource returnis = null;
    using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(fileName))
    {
        IntPtr hBitmap = GenerateThumbnail(bmp, 50);
        try
        {
           returnis = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                        hBitmap,
                        IntPtr.Zero,
                        Int32Rect.Empty,
                        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
                }
                finally
                {
                    DeleteObject(hBitmap);
                }
            }
            return returnis;
        }

/// <summary>
/// GenerateThumbnail image.
/// </summary>
/// <param name="original">Image</param>
/// <param name="percentage">int</param>
/// <returns>Image</returns>

public static IntPtr GenerateThumbnail(System.Drawing.Image original, int percentage)
{
    try
    {
        if (percentage < 1)
        {
            throw new Exception("Thumbnail size must be at least 1% of the original size.");
        }
        Bitmap tn = new Bitmap((int)(original.Width * 0.01f * percentage), (int)(original.Height * 0.01f * percentage));
        Graphics g = Graphics.FromImage(tn);
        g.InterpolationMode = InterpolationMode.HighQualityBilinear;

        //Experiment with this...
        g.DrawImage(original,
                    new System.Drawing.Rectangle(0, 0, tn.Width, tn.Height),
                    0,
                    0,
                    original.Width,
                    original.Height,
                    GraphicsUnit.Pixel);
        g.Dispose();
        return tn.GetHbitmap();
    }
    catch (Exception ex)
    {
        return IntPtr.Zero;
    }
}