-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

ラージ オブジェクト ヒープ (LOH) の断片化に苦しんでいることをお勧めします。画像サイズを 85K バイト未満に縮小して、LOH にヒットしないようにする方法はありますか?

于 2013-09-11T15:56:37.663 に答える
0

私は同じ状況に直面していますが、今は別の状況でこれを終わらせなければなりませんでした。それを共有します.

ここでは、サムネイル ビューのリストビュー アイテムに画像を追加するために投稿しました。同様に、画像の幅と高さを変更することで、bitmapsource オブジェクトの戻り値から必要なものを取得できます。

ステップ1

DLL ファイル file をインポートします。

[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;
    }
}
于 2014-02-07T08:21:53.077 に答える
0

.NET 4.5.1 を使用している場合は、オンデマンドの LOH コンパクションを実行できます。

于 2013-09-14T03:15:43.457 に答える