Подтвердить что ты не робот

Приложение 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);
        }
    }
4b9b3361

Ответ 1

Вместо control.Dispatcher.Invoke try control.Dispatcher.BeginInvoke, что помогло мне раньше в таких случаях.

Кроме того, ваш код кажется мне немного странным. В моем приложении я установил обработчик события AppDomain.CurrentDomain.UnhandledException в главное окно Loaded(). Событие привязано к локальному методу главного окна. Таким образом, мне не нужно делать вызов Dispatcher, потому что событие уже поднято в главном потоке диспетчера, даже если ошибка вообще происходит в другом потоке.