我正在创建一个应用程序,我从相机获取实时图像并尝试将其置于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)
有没有办法可以减少内存消耗并找到解决这种内存不足异常的方法?
答案 0 :(得分:0)
我建议您患有大型物体堆(LOH)碎片。有没有办法可以将图像尺寸减小到85K字节以下,这样它们就不会达到LOH?
答案 1 :(得分:0)
如果您使用的是.NET 4.5.1,则可以执行on-demand LOH compaction。
答案 2 :(得分:0)
我确实面临同样的情况,现在我必须用另一个完成这个,我会分享它。
这里我发布了在列表视图项目中为缩略图视图添加图像。同样,通过更改图像的宽度和高度,您可以通过bitmapsource对象的返回值获得所需的内容。
导入DLL文件文件:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
/// <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;
}
}