-1

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

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

4

3 回答 3

0

I do face the same situation, and now I had to finish this with an alternate one, and I will share that.

Here I have posted for adding images in a listview item for a thumbnail view. Similarly, by changing the width and height of an image you can get what you wanted through the return value of a bitmapsource object.

Step 1

Import the DLL file file:

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

Step 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;
    }
}
于 2014-02-07T08:21:53.077 回答
0

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

于 2013-09-14T03:15:43.457 回答
0

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

于 2013-09-11T15:56:37.663 回答