WPF 应用程序中的线程抛出 System.OutOfMemoryException
Thread throw System.OutOfMemoryException in WPF application
以下代码将在应用程序执行处理以显示进度时调用另一个线程windows。我们做多次就会抛出异常,比如命中超过50次。
这是我们的代码 - BusyIndicatorHelper.ShowProgWindowCustomSize 从异常中抛出并将调用以下代码。
public void ShowBusyIndicatorCustomSize(string message, WindowCustom currentWindow, bool fileTransferStatus = false)
{
_message = message;
using (_progressWindowWaitHandle = new AutoResetEvent(false))
{
_transferLoadVisibility = fileTransferStatus;
//Starts the progress window thread
Thread newprogWindowThread = new Thread(() => ShowProgWindowCustomSize(currentWindow));
//new Thread(new ThreadStart(ShowProgWindowNew(height, width, left, right)));
newprogWindowThread.SetApartmentState(ApartmentState.STA);
newprogWindowThread.IsBackground = true;
newprogWindowThread.Start();
//Wait for thread to notify that it has created the window
_progressWindowWaitHandle.WaitOne();
_isActive = true;
}
}
这将调用 ShowProgWindowCustomSize(currentWindow),如下所示。
private void ShowProgWindowCustomSize(WindowCustom currentWindow)
{
if (_transferLoadVisibility)
{
//creates and shows the progress window
progWindow = new LoadingWindow(_message);
progWindow.Height = currentWindow.WindowHeight;
progWindow.Width = currentWindow.WindowWidth;
progWindow.Left = currentWindow.WindowLeft;
progWindow.Top = currentWindow.WindowTop;
progWindow.WindowState = currentWindow.WindowState;
progWindow.FileTansfer();
progWindow.Show();
}
else
{
//creates and shows the progress window
progWindow = new LoadingWindow(_message);
progWindow.Height = currentWindow.WindowHeight;
progWindow.Width = currentWindow.WindowWidth;
progWindow.Left = currentWindow.WindowLeft;
progWindow.Top = currentWindow.WindowTop;
progWindow.WindowState = currentWindow.WindowState;
progWindow.Show();
}
//makes sure dispatcher is shut down when the window is closed
progWindow.Closed += (s, e) => Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
//Notifies command thread the window has been created
_progressWindowWaitHandle.Set();
//Starts window dispatcher
System.Windows.Threading.Dispatcher.Run();
}
以下是抛出的outofmemory异常
Application: BioMedicalVerification.exe Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.OutOfMemoryException Stack: at
System.Windows.Media.Composition.DUCE+Channel.SyncFlush() at
System.Windows.Media.MediaContext.CompleteRender() at
System.Windows.Interop.HwndTarget.OnResize() at
System.Windows.Interop.HwndTarget.HandleMessage
(MS.Internal.Interop.WindowMessage, IntPtr, IntPtr) at
System.Windows.Interop.HwndSource.HwndTargetFilterMessage (IntPtr,
Int32, IntPtr, IntPtr, Boolean ByRef) at MS.Win32.HwndWrapper.WndProc
(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef) at
MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object) at
System.Windows.Threading.ExceptionWrapper.InternalRealCall
(System.Delegate, System.Object, Int32) at
System.Windows.Threading.ExceptionWrapper.TryCatchWhen (System.Object,
System.Delegate, System.Object, Int32, System.Delegate) at
System.Windows.Threading.Dispatcher.LegacyInvokeImpl
(System.Windows.Threading.DispatcherPriority, System.TimeSpan,
System.Delegate, System.Object, Int32) at
MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32,
IntPtr, IntPtr) at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr,
Int32, IntPtr, IntPtr) at
MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32,
IntPtr, IntPtr) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr,
Int32, IntPtr, IntPtr) at MS.Win32.UnsafeNativeMethods.SetWindowPos
(System.Runtime.InteropServices.HandleRef,
System.Runtime.InteropServices.HandleRef, Int32, Int32, Int32, Int32,
Int32) at System.Windows.Window.SetupInitialState(Double, Double,
Double, Double) at System.Windows.Window.CreateSourceWindow(Boolean)
at System.Windows.Window.CreateSourceWindowDuringShow() at
System.Windows.Window.SafeCreateWindowDuringShow() at
System.Windows.Window.ShowHelper(System.Object) at
System.Windows.Window.Show() at
Org.Bestinet.BV.Presentation.UI.BusyIndicatorHelper.ShowProgWindowCustomSize
(Org.Bestinet.BV.Presentation.UI.WindowCustom) at
Org.Bestinet.BV.Presentation.UI.BusyIndicatorHelper+<>
c__DisplayClass2.<ShowBusyIndicatorCustomSize>b__0() at
System.Threading.ThreadHelper.ThreadStart_Context(System.Object) at
System.Threading.ExecutionContext.RunInternal
(System.Threading.ExecutionContext, System.Threading.ContextCallback,
System.Object, Boolean) at System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext, System.Threading.ContextCallback,
System.Object, Boolean) at System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext, System.Threading.ContextCallback,
System.Object) at System.Threading.ThreadHelper.ThreadStart()
我怀疑是因为 VerifyFinger 函数,因为这是我们检查指纹图像的地方
BusyIndicatorHelper busyIndicatorHelper = new BusyIndicatorHelper();
List<WorkerDO> docList = new
DatabaseHelper().SearchDocInfo(UserContext.VdrInfo.WorkerObj.WrkrId);
if (docList != null && docList.Count > 0)
{ busyIndicatorHelper.ShowBusyIndicatorCustomSize("Verification",
WindowSetting.GetCurrentWindowState(this));
FingerPrintHelper fp = null;
if (_fpHelper != null)
fp = _fpHelper;
else
fp = FingerPrintHelper.GetFingerPrinterHelperObj;
verifyStatus = fp.VerifyFinger(docList, _viewModel.DetectedFingers,
IsIndexFingerSelected);
docList = null;
_viewModel.DetectedFingers = null;
}
每次调用此方法时,您都会在新线程上创建一个新的 LoadingWindow 对象。
progWindow = new LoadingWindow(_message);
您是否在创建新 LoadingWindow 之前释放之前的 LoadingWindow?
为什么要关闭 CurrentDispatcher
?它是您程序的唯一一个,您的代码将永远不会执行关闭。所以每次你打开你的BusyWindow
,都会创建新的线程(-1MB
从你的内存中),它会陷入死循环,消耗另一部分系统资源。最终您的程序将超出内存,正如您的异常所述,这是发生的。
您真的不应该为您的任务启动一个新线程 - 使用更高级别的抽象,可能是 ThreadPool
or Task Parallel Library
。这将有助于消除代码中的内存泄漏。
更新:
我在你的新代码中看到这样一行:
_viewModel.DetectedFingers = null;
我怀疑这是一个 Image
you got from client. If so, you can't simply set it to null
, you must Dispose()
它来释放你的图形资源,像这样:
verifyStatus = fp.VerifyFinger(docList, _viewModel.DetectedFingers,
IsIndexFingerSelected);
docList = null;
_viewModel.DetectedFingers.Dispose();
_viewModel.DetectedFingers = null;
问题已找到。这不是因为 WPF 代码,而是因为我们使用的 SDK 内存不足。
问题已解决。谢谢。
以下代码将在应用程序执行处理以显示进度时调用另一个线程windows。我们做多次就会抛出异常,比如命中超过50次。 这是我们的代码 - BusyIndicatorHelper.ShowProgWindowCustomSize 从异常中抛出并将调用以下代码。
public void ShowBusyIndicatorCustomSize(string message, WindowCustom currentWindow, bool fileTransferStatus = false)
{
_message = message;
using (_progressWindowWaitHandle = new AutoResetEvent(false))
{
_transferLoadVisibility = fileTransferStatus;
//Starts the progress window thread
Thread newprogWindowThread = new Thread(() => ShowProgWindowCustomSize(currentWindow));
//new Thread(new ThreadStart(ShowProgWindowNew(height, width, left, right)));
newprogWindowThread.SetApartmentState(ApartmentState.STA);
newprogWindowThread.IsBackground = true;
newprogWindowThread.Start();
//Wait for thread to notify that it has created the window
_progressWindowWaitHandle.WaitOne();
_isActive = true;
}
}
这将调用 ShowProgWindowCustomSize(currentWindow),如下所示。
private void ShowProgWindowCustomSize(WindowCustom currentWindow)
{
if (_transferLoadVisibility)
{
//creates and shows the progress window
progWindow = new LoadingWindow(_message);
progWindow.Height = currentWindow.WindowHeight;
progWindow.Width = currentWindow.WindowWidth;
progWindow.Left = currentWindow.WindowLeft;
progWindow.Top = currentWindow.WindowTop;
progWindow.WindowState = currentWindow.WindowState;
progWindow.FileTansfer();
progWindow.Show();
}
else
{
//creates and shows the progress window
progWindow = new LoadingWindow(_message);
progWindow.Height = currentWindow.WindowHeight;
progWindow.Width = currentWindow.WindowWidth;
progWindow.Left = currentWindow.WindowLeft;
progWindow.Top = currentWindow.WindowTop;
progWindow.WindowState = currentWindow.WindowState;
progWindow.Show();
}
//makes sure dispatcher is shut down when the window is closed
progWindow.Closed += (s, e) => Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
//Notifies command thread the window has been created
_progressWindowWaitHandle.Set();
//Starts window dispatcher
System.Windows.Threading.Dispatcher.Run();
}
以下是抛出的outofmemory异常
Application: BioMedicalVerification.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.OutOfMemoryException Stack: at System.Windows.Media.Composition.DUCE+Channel.SyncFlush() at System.Windows.Media.MediaContext.CompleteRender() at System.Windows.Interop.HwndTarget.OnResize() at System.Windows.Interop.HwndTarget.HandleMessage (MS.Internal.Interop.WindowMessage, IntPtr, IntPtr) at System.Windows.Interop.HwndSource.HwndTargetFilterMessage (IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef) at MS.Win32.HwndWrapper.WndProc (IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object) at System.Windows.Threading.ExceptionWrapper.InternalRealCall (System.Delegate, System.Object, Int32) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen (System.Object, System.Delegate, System.Object, Int32, System.Delegate) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl (System.Windows.Threading.DispatcherPriority, System.TimeSpan,
System.Delegate, System.Object, Int32) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr) at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr) at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr) at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr, IntPtr) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr) at MS.Win32.UnsafeNativeMethods.SetWindowPos (System.Runtime.InteropServices.HandleRef,
System.Runtime.InteropServices.HandleRef, Int32, Int32, Int32, Int32, Int32) at System.Windows.Window.SetupInitialState(Double, Double, Double, Double) at System.Windows.Window.CreateSourceWindow(Boolean) at System.Windows.Window.CreateSourceWindowDuringShow() at System.Windows.Window.SafeCreateWindowDuringShow() at System.Windows.Window.ShowHelper(System.Object) at System.Windows.Window.Show() at
Org.Bestinet.BV.Presentation.UI.BusyIndicatorHelper.ShowProgWindowCustomSize (Org.Bestinet.BV.Presentation.UI.WindowCustom) at
Org.Bestinet.BV.Presentation.UI.BusyIndicatorHelper+<> c__DisplayClass2.<ShowBusyIndicatorCustomSize>b__0() at System.Threading.ThreadHelper.ThreadStart_Context(System.Object) at
System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) at System.Threading.ThreadHelper.ThreadStart()
我怀疑是因为 VerifyFinger 函数,因为这是我们检查指纹图像的地方
BusyIndicatorHelper busyIndicatorHelper = new BusyIndicatorHelper();
List<WorkerDO> docList = new
DatabaseHelper().SearchDocInfo(UserContext.VdrInfo.WorkerObj.WrkrId);
if (docList != null && docList.Count > 0)
{ busyIndicatorHelper.ShowBusyIndicatorCustomSize("Verification",
WindowSetting.GetCurrentWindowState(this));
FingerPrintHelper fp = null;
if (_fpHelper != null)
fp = _fpHelper;
else
fp = FingerPrintHelper.GetFingerPrinterHelperObj;
verifyStatus = fp.VerifyFinger(docList, _viewModel.DetectedFingers,
IsIndexFingerSelected);
docList = null;
_viewModel.DetectedFingers = null;
}
每次调用此方法时,您都会在新线程上创建一个新的 LoadingWindow 对象。
progWindow = new LoadingWindow(_message);
您是否在创建新 LoadingWindow 之前释放之前的 LoadingWindow?
为什么要关闭 CurrentDispatcher
?它是您程序的唯一一个,您的代码将永远不会执行关闭。所以每次你打开你的BusyWindow
,都会创建新的线程(-1MB
从你的内存中),它会陷入死循环,消耗另一部分系统资源。最终您的程序将超出内存,正如您的异常所述,这是发生的。
您真的不应该为您的任务启动一个新线程 - 使用更高级别的抽象,可能是 ThreadPool
or Task Parallel Library
。这将有助于消除代码中的内存泄漏。
更新:
我在你的新代码中看到这样一行:
_viewModel.DetectedFingers = null;
我怀疑这是一个 Image
you got from client. If so, you can't simply set it to null
, you must Dispose()
它来释放你的图形资源,像这样:
verifyStatus = fp.VerifyFinger(docList, _viewModel.DetectedFingers,
IsIndexFingerSelected);
docList = null;
_viewModel.DetectedFingers.Dispose();
_viewModel.DetectedFingers = null;
问题已找到。这不是因为 WPF 代码,而是因为我们使用的 SDK 内存不足。
问题已解决。谢谢。