2012-02-14 17 views
13

Ocasionalmente, tenemos una situación en la que la aplicación está en punto muerto y parece que el despachador está bloqueado con una cadena de fondo que intenta invocar en el despachador. No veo que ninguno de los hilos tenga recursos compartidos que estén bloqueados. El hilo de fondo ha encontrado una excepción y termina en el delegado de excepción no controlada del dominio de la aplicación porque nadie recogió esta excepción. Esto llama a nuestro controlador de excepción que tiene la tarea de asegurar que nuestro diálogo de excepción se ponga en el despachador.La aplicación WPF está bloqueada al invocar en el Dispatcher

¿Alguien puede sugerir formas en que puedo descubrir qué está causando el punto muerto?

La pila despachador sigue y no se ve fuera de lo común:

*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) 

Los segundos hilos pila comienza bascically del dominio de aplicación no controlada gestor de excepciones:

*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) 

Parece ser que la Invoke está esperando como se esperaba pero también parece que el subproceso del asignador está bloqueado. Hemos esperado muchos minutos en estas situaciones y la aplicación nunca vuelve. Cualquier ayuda o vision sería apreciada. Sé que puedo cambiar a BeginInvoke, pero en función del contexto aquí me preocupa que mi hilo de fondo continúe y que la IU esté bloqueada por el mismo motivo o que no aparezca el diálogo de excepción.

Nuestro hilo de fondo ejecuta el siguiente flujo de código cuando la excepción se presenta en el manejador de excepción no controlada de 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); 
     } 
    } 
+0

¿Puedes publicar tu código? – Rachel

+0

Publiqué el código que se ejecuta a partir del controlador de excepciones de dominio no administrado de la aplicación. – Ben

+0

Sería más interesante ver la traza de pila de la hebra de UI mientras el interbloqueo está activo. El subproceso de interfaz de usuario probablemente esté esperando algo, por lo que el despachador se bloquea. Interrumpa el depurador la próxima vez que se produzca el interbloqueo y compruebe el seguimiento de la pila del subproceso de interfaz de usuario. ¿Podría ser que su subproceso de interfaz de usuario esté en un Thread.Join (o algo similar) mientras que el subproceso de fondo intenta invocar en el despachador? Dejé de usar Invoke hace mucho tiempo debido a los bloqueos ... solo BeginInvoke. – stmax

Respuesta

1

En lugar de tratar control.Dispatcher.Invokecontrol.Dispatcher.BeginInvoke, que me ha ayudado antes en tales casos de esquina.

Además, su código me parece un poco extraño. En mi aplicación, establecí el controlador de eventos AppDomain.CurrentDomain.UnhandledException en el evento de la ventana principal Loaded(). El evento está adjunto a un método local de la ventana principal. Como tal, no necesito hacer ninguna invocación de Dispatcher, porque el evento ya se ha generado en la secuencia principal del asignador, incluso si el error ocurre en otro hilo por completo.

+0

No siempre es posible simplemente cambiar de 'Invoke' a' BeginInvoke'. El primero es sincrónico, y el segundo es asincrónico. Si el llamado entrante depende de los efectos de la llamada invocada, podría ser así de fácil. –

Cuestiones relacionadas