Reputation: 41
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;
}
Upvotes: 4
Views: 2960
Reputation: 41
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.
Upvotes: 0
Reputation: 28356
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;
Upvotes: 2
Reputation: 62
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?
Upvotes: -1