We have a WPF busy window indicator. It is displayed in the main thread using window.ShowDialog(). When you respond to the Loaded event, an action is taken and the window closes, so the application continues to work.
It seems to window.ShowDialog()freeze from time to time (very rarely) without showing a dialog, and the Loaded event does not fire, so the application freezes. The related code is as follows:
private void BusyIndicatorAsyncCall(string text, Action<DoWorkEventArgs> doWorkDinamicView = null, Action doWork = null, Action workCompleted = null, Action<Exception> exceptionReturn = null)
{
Window window = this.CreateWindowOfBusyIndicator(text);
Dispatcher dispatcher = window.Dispatcher;
BackgroundWorker backgoundworker = new BackgroundWorker();
IViewModel viewModel = (window.Content as UserControl).DataContext as IViewModel;
this.Modals.Add(viewModel, window);
if (doWorkDinamicView != null)
{
DoWorkEventArgs eventArgs = new DoWorkEventArgs(window.Content);
backgoundworker.DoWork += (s, e) => doWorkDinamicView.Invoke(eventArgs);
}
else if (doWork != null)
{
backgoundworker.DoWork += (s, e) => { doWork.Invoke(); };
}
backgoundworker.RunWorkerCompleted += (s, e) =>
{
Exception exception = e.Error;
if (exception == null)
{
if (workCompleted != null)
{
try
{
this.StyleName = null;
workCompleted.Invoke();
}
catch (Exception ex)
{
exception = ex;
}
}
}
this.Modals.Remove(viewModel);
dispatcher.Invoke(new Action(window.Close));
if (exception != null)
{
if (exceptionReturn == null)
throw new Exception("Error en RunWorkerCompleted.", exception);
else
exceptionReturn(exception);
}
};
RoutedEventHandler onLoaded = new RoutedEventHandler((sender, e) =>
{
try
{
backgoundworker.RunWorkerAsync();
}
catch
{
}
});
this.BusyIndicatorImpl(window, onLoaded);
}
private void BusyIndicatorImpl(Window window, RoutedEventHandler onLoaded)
{
window.Loaded += onLoaded;
window.ShowDialog();
window.Loaded -= onLoaded;
}
When the application freezes, I see the instruction pointer by the method window.ShowDialog(), but the window does not appear in the application, and backgroundWorker is not running yet, so I assume that the OnLoaded event has not been generated.
, , . , , Windows 7.
, , :
user32.dll!_NtUserGetMessage@16() + 0x15 bytes
user32.dll!_NtUserGetMessage@16() + 0x15 bytes
[Managed to Native Transition]
WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + 0x14 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x80 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x75 bytes WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox) + 0x17d bytes
PresentationFramework.dll!System.Windows.Window.Show() + 0x5c bytes
PresentationFramework.dll!System.Windows.Window.ShowDialog() + 0x27d bytes
> xxx.dll!xxx.BusyIndicatorImpl(System.Windows.Window window, System.Windows.RoutedEventHandler onLoaded) Line 743 + 0xd bytes C#
, , Visual Studio , . , :
Debugger Thread ID Managed Thread ID OS Thread ID Thread Object GC Mode Domain Lock Count Apt Exception
0 1 5684 2b2390 Preemptive 9176600 0 STA
6 2 5572 2c7a80 Preemptive 2a82f8 0 MTA (Finalizer)
7 3 3676 2cb828 Preemptive 2a82f8 0 Unknown
11 4 864 7f7d5c0 Preemptive 2a82f8 0 MTA (Threadpool Worker)
15 10 4340 921cdc8 Preemptive 9176600 1 MTA
16 12 1648 9438560 Preemptive 2a82f8 0 MTA (Threadpool Completion Port)
17 14 3380 9001038 Preemptive 2a82f8 0 Unknown (Threadpool Worker)
21 7 5336 9002fe8 Preemptive 2a82f8 0 MTA (Threadpool Worker)
20 5 4120 9003fc0 Preemptive 2a82f8 0 MTA (Threadpool Worker)
25 18 5172 9004508 Preemptive 2a82f8 0 MTA (Threadpool Worker)
27 11 5772 9003a78 Preemptive 2a82f8 0 MTA (Threadpool Worker)
(0, 1 ShowDialog). , 15 ( 10) .Net.
15 ( 10), , :
[[HelperMethodFrame_1OBJ] (System.Threading.WaitHandle.WaitMultiple)] System.Threading.WaitHandle.WaitMultiple(System.Threading.WaitHandle[], Int32, Boolean, Boolean)
mscorlib_ni!System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[], Int32, Boolean)+92
System_ni!System.Net.TimerThread.ThreadProc()+28f
mscorlib_ni!System.Threading.ThreadHelper.ThreadStart_Context(System.Object)+6f
mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+a7
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+16
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+41
mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+44
[[GCFrame]]
[[DebuggerU2MCatchHandlerFrame]]
[[ContextTransitionFrame]]
[[DebuggerU2MCatchHandlerFrame]]
, , , , , , , .
, . WinDbg, , .
:
:
, dispatcher.Invoke(new Action(window.Close)); , window.ShowDialog(); .
Spy ++ , , , , window.ShowDialog(); .
, , .