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

本文关键字:内存不足 异常 应用程序 WPF | 更新日期: 2023-09-27 18:31:01

我正在创建一个应用程序,我正在从相机获取实时图像,并尝试将其放在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)

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

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

我建议你遭受大型对象堆(LOH)碎片的困扰。有什么方法可以将图像大小减小到 85K 字节以下,这样它们就不会击中 LOH?

如果您使用的是 .NET 4.5.1,则可以按需执行 LOH 压缩。

我确实面临同样的情况,现在我不得不用另一个来完成这个,我将分享这一点。

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

步骤 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;
    }
}