Приложение WPF заходит в тупик при вызове диспетчера

Иногда мы сталкиваемся с ситуацией, когда приложение заходит в тупик, и кажется, что диспетчер зашел в тупик, а фоновый поток пытается вызвать диспетчер. Я не вижу, чтобы какой-либо поток имел заблокированные общие ресурсы. Фоновый поток обнаружил исключение и попадает в делегат необработанного исключения домена приложения, потому что это исключение никто не уловил. Это вызывает наш обработчик исключений, задачей которого является обеспечение того, чтобы наш диалог исключения был помещен в диспетчер.

Может ли кто-нибудь предложить способы выяснить, что вызывает тупик?

Стек диспетчера следует и не выглядит необычным:

*0. System.Windows.Threading.DispatcherSynchronizationContext.Wait (source line information unavailable)

 1. System.Threading.SynchronizationContext.InvokeWaitMethodHelper (source line information unavailable)
 2. Xceed.Wpf.DataGrid.DeferredOperationManager.Process (source line information unavailable)
 3. Xceed.Wpf.DataGrid.DeferredOperationManager.Dispatched_Process (source line information unavailable)
 4. System.Windows.Threading.ExceptionWrapper.InternalRealCall (source line information unavailable)
 5. System.Windows.Threading.ExceptionWrapper.TryCatchWhen (source line information unavailable)
 6. System.Windows.Threading.Dispatcher.WrappedInvoke (source line information unavailable)
 7. System.Windows.Threading.DispatcherOperation.InvokeImpl (source line information unavailable)
 8. System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext (source line information unavailable)
 9. System.Threading.ExecutionContext.runTryCode (source line information unavailable)
 10. System.Threading.ExecutionContext.RunInternal (source line information unavailable)
 11. System.Threading.ExecutionContext.Run (source line information unavailable)
 12. System.Windows.Threading.DispatcherOperation.Invoke (source line information unavailable)
 13. System.Windows.Threading.Dispatcher.ProcessQueue (source line information unavailable
 14. System.Windows.Threading.Dispatcher.WndProcHook (source line information unavailable)
 15. MS.Win32.HwndWrapper.WndProc (source line information unavailable)
 16. MS.Win32.HwndSubclass.DispatcherCallbackOperation (source line information unavailable)
 17. System.Windows.Threading.ExceptionWrapper.InternalRealCall (source line information unavailable)
 18. System.Windows.Threading.ExceptionWrapper.TryCatchWhen (source line information unavailable)
 19. System.Windows.Threading.Dispatcher.WrappedInvoke (source line information unavailable)
 20. System.Windows.Threading.Dispatcher.InvokeImpl (source line information unavailable)
 21. System.Windows.Threading.Dispatcher.Invoke (source line information unavailable)
 22. MS.Win32.HwndSubclass.SubclassWndProc (source line information unavailable)
    [Internal Frame, 'M-->U']
 23. System.Windows.Threading.Dispatcher.PushFrameImpl (source line information unavailable)
 24. System.Windows.Threading.Dispatcher.PushFrame (source line information unavailable)
 25. System.Windows.Threading.Dispatcher.Run (source line information unavailable)
 26. System.Windows.Application.RunDispatcher (source line information unavailable)
 27. System.Windows.Application.RunInternal (source line information unavailable)
 28. System.Windows.Application.Run (source line information unavailable)
 29. System.Windows.Application.Run (source line information unavailable)
 30. Wmc.Gtseq.Client.Desktop.App.Main (source line information unavailable)

Второй стек потоков запускается в основном из обработчика необработанных исключений домена приложения:

*0. System.Threading.WaitHandle.WaitOne (source line information unavailable)

 1. System.Threading.WaitHandle.WaitOne (source line information unavailable)
 2. System.Windows.Threading.DispatcherOperation+DispatcherOperationEvent.WaitOne (source line information unavailable)
 3. System.Windows.Threading.DispatcherOperation.Wait (source line information unavailable)
 4. System.Windows.Threading.Dispatcher.InvokeImpl (source line information unavailable)
 5. System.Windows.Threading.Dispatcher.Invoke (source line information unavailable)
 6. Wmc.Gtseq.Core.ForwardPort.Extensions.DispatcherExtension.InvokeIfRequired (source line information unavailable)
 7. Wmc.Gtseq.Core.ForwardPort.Utilities.DispatcherHelper.InvokeOnMainThread (source line information unavailable)
 8. Wmc.Gtseq.Core.ForwardPort.Handlers.ExceptionHandler.ThreadSafeDialogHandler (source line information unavailable)
 9. Wmc.Gtseq.Core.ForwardPort.Handlers.ExceptionHandler.ShowErrorDialog (source line information unavailable)
 10. Wmc.Gtseq.Core.ForwardPort.Handlers.ExceptionHandler.HandleException (source line information unavailable)
 11. Wmc.Gtseq.Client.Desktop.App.AppDomainUnhandledException (source line information unavailable)

Похоже, что Invoke ожидает, как и ожидалось, но также кажется, что сам поток диспетчера заблокирован. В таких ситуациях мы ждали несколько минут, и приложение больше не возвращается. Любая помощь или понимание будут оценены. Я знаю, что могу переключиться на BeginInvoke, но в зависимости от контекста здесь я беспокоюсь, что мой фоновый поток продолжится и пользовательский интерфейс будет заблокирован по той же причине, или диалоговое окно исключения не появится.

Наш фоновый поток выполняет следующий поток кода, когда исключение обнаруживается в обработчике необработанных исключений домена:

protected override void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        ExceptionHandler.HandleException(e.ExceptionObject as Exception, false);
    }

public static void HandleException(Exception ex, bool closeApp)
    {
        ThreadSafeDialogHandler((Action)delegate { ErrorDialog.ShowDialog(ex, closeApp); });           
    }

private static void ThreadSafeDialogHandler(Action methodCall)
    {
        DispatcherHelper.InvokeOnMainThread(() => { methodCall(); });
    }

public static void InvokeOnMainThread(Action method)
    {
        Application.Current.InvokeIfRequired(method, DispatcherPriority.Normal);
    }

public static void InvokeIfRequired(this DispatcherObject control, Action methodcall, DispatcherPriority priorityForCall)
    {
        // see if we need to Invoke call to Dispatcher thread  
        if (control.Dispatcher.CheckAccess())
        {
            methodcall();
        }
        else
        {
            control.Dispatcher.Invoke(priorityForCall, methodcall);
        }
    }
14
задан Matas Vaitkevicius 29 September 2014 в 15:41
поделиться