WPF应用程序

时间:2016-01-27 06:26:00

标签: c# wpf multithreading out-of-memory

当应用程序执行处理以显示进度窗口时,以下代码将调用另一个线程。在我们多次执行后会抛出异常,例如命中次数超过50次。 这是我们的代码 - 从异常抛出的BusyIndi​​catorHelper.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异常。

  

应用程序:BioMedicalVerification.exe Framework版本: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   (MS.Internal.Interop.WindowMessage,IntPtr,IntPtr)at   System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr,   在MS.Win32.HwndWrapper.WndProc上的Int32,IntPtr,IntPtr,Boolean ByRef)   (IntPtr,Int32,IntPtr,IntPtr,Boolean ByRef)at   MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)at 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)   在MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr,IntPtr,Int32,   IntPtr,IntPtr)在MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr,   Int32,IntPtr,IntPtr)at   MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr,IntPtr,Int32,   IntPtr,IntPtr)在MS.Win32.HwndSubclass.SubclassWndProc(IntPtr,   Int.32,IntPtr,IntPtr)在MS.Win32.UnsafeNativeMethods.SetWindowPos   (System.Runtime.InteropServices.HandleRef,
  System.Runtime.InteropServices.HandleRef,Int32,Int32,Int32,Int32,   Int32)在System.Windows.Window.SetupInitialState(Double,Double,   System.Windows.Window.CreateSourceWindow(Boolean)中的Double,Double)   在System.Windows.Window.CreateSourceWindowDuringShow()中   System.Windows.Window.SafeCreateWindowDuringShow()at   System.Windows.Window.ShowHelper(System.Object)at   System.Windows.Window.Show()在   Org.Bestinet.BV.Presentation.UI.BusyIndi​​catorHelper.ShowProgWindowCustomSize   (Org.Bestinet.BV.Presentation.UI.WindowCustom)在   Org.Bestinet.BV.Presentation.UI.BusyIndi​​catorHelper + LT;>   c__DisplayClass2。< ShowBusyIndi​​catorCustomSize> b__0()at   在。的System.Threading.ThreadHelper.ThreadStart_Context(System.Object)   System.Threading.ExecutionContext.RunInternal   (System.Threading.ExecutionContext,System.Threading.ContextCallback,   System.Threading.ExecutionContext.Run中的System.Object,Boolean)   (System.Threading.ExecutionContext,System.Threading.ContextCallback,   System.Threading.ExecutionContext.Run中的System.Object,Boolean)   (System.Threading.ExecutionContext,System.Threading.ContextCallback,   System.Threading.ThreadHelper.ThreadStart()

中的System.Object)

我怀疑因为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;
}

3 个答案:

答案 0 :(得分:1)

为什么要关闭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;

答案 1 :(得分:0)

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

问题已解决。感谢。

答案 2 :(得分:-1)

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

progWindow = new LoadingWindow(_message);

您是否在创建新的之前释放了之前的LoadingWindow?