4
votes

The following code will call another thread when the application doing the processing to show the progress windows. It will throw an exception after we do multiple time, for example hit more than 50 times. This is our code - BusyIndicatorHelper.ShowProgWindowCustomSize as thrown from the exception and will call the following code.

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

This will call ShowProgWindowCustomSize(currentWindow) as in the following.

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

The following are the outofmemory exception being thrown.

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()

I suspect because of the VerifyFinger function as this is where we do the checking for the finger print image

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
This is definitely not related to that "wait" dialog, but to logic being executed while this window is displayed. You show us the source code for that window, which does not make any sense. You should instead show what is going on while this window is displayeduser586399
Can you share WindowCustom code? Both XAML and codebehind? It might be related to what is happening inside of it.VidasV

3 Answers

1
votes

Why do you close the CurrentDispatcher? It's the only one for your program, and your code will never execute the shutdown. So each time you open your BusyWindow, the new thread is being created (- 1MB from your memory), and it falls into infinite loop, which consumes another part of system resources. Eventually your program will get out of the memory, which is happen, as your exception states.

You really should not start a new thread for your task - use higher lever of abstraction, may be ThreadPool or Task Parallel Library. this will help remove memory leaks from your code.

Update:
I see in your new code such line:

_viewModel.DetectedFingers = null;

I suspect that this is an Image you got from client. If so, you can't simply set it to null, you must Dispose() it to free your graphical resources, like this:

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

The issue was found. It's not because of the WPF code but due the SDK that we are using out of memory.

Issue resolved. Thanks.

-1
votes

Each time you call this method you are creating a new LoadingWindow object on a new thread.

progWindow = new LoadingWindow(_message);

Are you freeing the prior LoadingWindow before creating the new one?