2009-02-17 27 views
5

Tengo una aplicación que se está bloqueando en el hilo de la GUI, y he usado WinDbg, junto con el comando "! Clrstack" para obtener este seguimiento de la pila, pero no puedo entender donde está el problema Todos estos métodos parecen métodos de marco, y ninguno es mío. Cualquier ayuda sería muy apreciada. Me disculpo por las líneas largasNecesito ayuda para descifrar un seguimiento de la pila C#

OS Thread Id: 0x724 (0) 
ESP  EIP  
0012ec88 7c90e4f4 [HelperMethodFrame_1OBJ: 0012ec88] System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean) 
0012ed34 792b687f System.Threading.WaitHandle.WaitOne(Int64, Boolean) 
0012ed50 792b6835 System.Threading.WaitHandle.WaitOne(Int32, Boolean) 
0012ed64 7b6f192f System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle) 
0012ed78 7ba2d0bb System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean) 
0012ee18 7b6f328c System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[]) 
0012ee4c 7b920717 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object) 
0012ee64 7a924102 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[]) 
0012ee98 7a922833 Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[]) 
0012eee4 7a923d2f Microsoft.Win32.SystemEvents.OnUserPreferenceChanged(Int32, IntPtr, IntPtr) 
0012ef04 7aa8f184 Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr) 
0012ef08 003620a4 [InlinedCallFrame: 0012ef08] 
0012f0cc 7b1d8cce System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32) 
0012f168 7b1d8937 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) 
0012f1bc 7b1d8781 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) 
0012f1ec 7b195911 System.Windows.Forms.Application.Run(System.Windows.Forms.Form) 
0012f200 00eb0ebb WinForms1.Program.Main() 
0012f69c 79e71b4c [GCFrame: 0012f69c] 
+0

¿Está intentando modificar un objeto de interfaz gráfica de usuario de un hilo que no lo posee? Si es así, podría encontrarse con el problema InvokeRequired. –

+0

Por lo que yo sé, no estoy haciendo ninguna operación de cruce de hilos. Creo que voy a tener una extensa revisión de código para rastrear esto. –

+0

Si alguien que está leyendo este hilo está tratando este problema de forma intermitente, una forma de forzar una reproducción es establecer una variable de entorno en un bucle. Aquí hay un ejemplo de archivo .cmd que establece una variable de entorno para todo el sistema cada ~ 5 segundos: código: top setx.exe foo bar ping.exe -n 5 localhost> nul goto top – JohnW

Respuesta

8

Parece que este código no es la verdadera causa del problema. A ver si una de estas páginas de ayuda:

Actualización: url fija a la primera página.

+0

Enlaces útiles, ¿alguna novedad para .net 3.x? –

+0

Supongo que .Net 3.x se comportará de la misma manera que .Net 2.0 en este caso ya que las DLL centrales son las mismas. – David

+0

Estoy bastante seguro de que este es el problema ... ahora solo es cuestión de rastrear el control ofensivo que se está creando en el hilo equivocado de alguna manera. –

1

Tuve un problema similar y encontré el culpable en nuestro código.

técnica utilizada: 0. Asegúrese de Spy ++ que sólo hay dos hilos no administrados con controles sobre ellos (WinForms y GDI +):

public static class ThreadingHelper_NativeMethods 
{ 
    [DllImport("user32.dll")] 
    public static extern bool IsGUIThread(bool bConvert); 
} 

llaman a esto a partir de hilos de interfaz de usuario en init:

// This code forces initialization of .NET BroadcastEventWindow to the UI thread. 
// http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/fb267827-1765-4bd9-ae2f-0abbd5a2ae22 
if (ThreadingHelper_NativeMethods.IsGUIThread(false)) 
{ 
    Microsoft.Win32.SystemEvents.InvokeOnEventsThread(new MethodInvoker(delegate() 
    { 
    int x = 0; 
    })); 
} 
  1. Recuerde la identificación administrada de Ui Thread en una clase singleton.

  2. Busque todos los UserControls definidos en nuestro código. En el constructor de cada control, antes de llamar a InitializeComponent(), coloqué un código que verifica el id. De subproceso actual contra el id. De subproceso principal. Si no son iguales, assert (falso).

  3. Suscríbete a SystemEvents.UserPreferencesChanging. Debug.Assert (false) en el controlador: esto ocurre antes de SystemEvents.UserPreferencesChanged, por lo que se espera que el depurador haga una pausa aquí.

  4. Inspeccione la lista de suscriptores a SystemEvents en el depurador. Encuentre un suscriptor en el diccionario de listas _handles. La apertura de SynchronizationContext de cada devolución de llamada debería revelar el problema: el mismo id. De subproceso que el control creado en el subproceso que no está en la interfaz de usuario. SystemEvents ejecutará el controlador de eventos en ese hilo, el bloqueo contra el hilo de UI.

+0

Excelentes consejos: ¡gracias! –

3

La otra respuesta viene de este Aaron Lerch. Me gusta mucho el apartado "punto de corte filtrado en el código de otra persona". Creo que me hubiera salvado un par de días.

http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/

+0

He tenido (y sigo teniendo) bastante buena suerte con eso, en cualquier caso. ;) –

Cuestiones relacionadas