Thread throw System.OutOfMemoryException in WPF application

本文关键字:WPF application in OutOfMemoryException throw System Thread | 更新日期: 2023-09-27 18:32:07

以下代码将在应用程序执行处理以显示进度窗口时调用另一个线程。在我们多次执行后,它会抛出异常,例如命中超过 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();
    }

以下是引发的内存不足异常。

应用:生物医学验证.exe框架版本:v4.0.30319 说明:由于未处理的异常,进程已终止。 异常信息: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 (女士。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 女士。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 女士。Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr) 在MS。Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr,IntPtr)在MS。Win32.HwndSubclass.DefWndProcWrapper(IntPtr, Int32, IntPtr, IntPtr) at 女士。Win32.UnsafeNativeMethods.CallWindowProc(IntPtr, IntPtr, Int32, IntPtr,IntPtr)在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.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()

我怀疑是因为验证手指功能,因为这是我们检查指纹图像的地方

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

Thread throw System.OutOfMemoryException in WPF application

为什么要关闭CurrentDispatcher?它是程序的唯一一个,您的代码永远不会执行关闭。因此,每次打开BusyWindow时,都会创建新线程(从内存中1MB),并且它陷入无限循环,这会消耗另一部分系统资源。最终,您的程序将退出内存,正如您的异常所述,这种情况正在发生。

你真的不应该为你的任务启动一个新线程 - 使用更高的抽象杠杆,可能是ThreadPoolTask Parallel Library。 这将有助于从代码中删除内存泄漏。

更新:
我在您的新代码中看到这样的行:

_viewModel.DetectedFingers = null;

我怀疑这是您从客户那里得到的Image。如果是这样,您不能简单地将其设置为 null ,您必须Dispose()它以释放您的图形资源,如下所示:

verifyStatus = fp.VerifyFinger(docList, _viewModel.DetectedFingers,  
IsIndexFingerSelected);
docList = null;
_viewModel.DetectedFingers.Dispose();
_viewModel.DetectedFingers = null;

发现问题。这不是因为 WPF 代码,而是因为我们使用的 SDK 内存不足。

问题已解决。谢谢。

每次调用此方法时,都会在新线程上创建一个新的 LoadWindow 对象。

progWindow = new LoadWindow(_message);

您是否在创建新加载窗口之前释放了以前的加载窗口?