Occasionalmente ci sono situazioni in cui l'applicazione è bloccata in un deadlock e sembra che il dispatcher sia bloccato in un deadlock con un thread in background che tenta di richiamare il dispatcher. Non vedo che entrambi i thread abbiano risorse condivise che sono bloccate. Il thread in background ha riscontrato un'eccezione e finisce nel delegato di eccezione non gestito del dominio dell'app perché nessuno ha rilevato questa eccezione. Questo chiama il nostro gestore di eccezioni che ha il compito di assicurare che la nostra finestra di dialogo delle eccezioni sia posta sul dispatcher.L'applicazione WPF è bloccata in caso di richiamo sul Dispatcher
Qualcuno può suggerire dei modi per capire che cosa sta causando il deadlock?
Lo stack dispatcher segue e non sembra fuori dal comune:
*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)
Il secondo discussioni impilano inizia bascically dal dominio applicazione gestore di eccezione non gestita:
*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)
Sembra che il Invoke è in attesa come previsto ma appare anche che il thread del dispatcher stesso è bloccato. Abbiamo aspettato molti minuti in queste situazioni e l'applicazione non ritorna mai. Qualsiasi aiuto o intuizione sarebbe apprezzato. So che posso passare a BeginInvoke ma in base al contesto qui mi preoccupo che il mio thread in background continui e che l'interfaccia utente sia bloccata per lo stesso motivo o la finestra di dialogo delle eccezioni non venga visualizzata.
nostro thread in background viene eseguito il seguente flusso di codice quando l'eccezione si presenta al gestore di eccezione non gestita di dominio:
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);
}
}
Puoi pubblicare il tuo codice? – Rachel
Ho pubblicato il codice che viene eseguito a partire dal gestore delle eccezioni non gestito del dominio dell'app. – Ben
Sarebbe più interessante vedere la traccia dello stack del thread dell'interfaccia utente mentre il deadlock è attivo. Il thread dell'interfaccia utente probabilmente sta aspettando qualcosa in modo che il dispatcher venga bloccato. Interrompere il debugger la volta successiva che si verifica il deadlock e controllare la traccia dello stack del thread dell'interfaccia utente. Potrebbe essere che il thread dell'interfaccia utente si trovi in un Thread.Join (o qualcosa di simile) mentre il thread in background tenta di eseguire Invoke sul dispatcher? Ho smesso di usare Invoke molto tempo fa a causa di deadlock .. solo BeginInvoke. – stmax