2009-02-17 12 views
5

Ho un'applicazione che blocca sul filo GUI, e ho usato WinDbg, insieme al "clrstack!" Il comando per ottenere questo traccia dello stack, ma io non riesco a capire dove si trova il problema Tutti questi metodi sembrano metodi quadro e nessuno è mio. Qualsiasi aiuto sarebbe molto apprezzato. Mi scuso per le lunghe codeHai bisogno di aiuto decifrare un C# traccia dello stack

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

Stai tentando di modificare un oggetto GUI da un thread che non possiedono? Se è così potresti essere in esecuzione nel problema InvokeRequired. –

+0

Per quanto ne so, non sto facendo nessuna operazione cross-thread. Penso che avrò un'estesa revisione del codice per rintracciarlo. –

+0

Se qualcuno che sta leggendo questa discussione si occupa di questo problema essendo intermittente, un modo per forzare una repro è impostare una variabile di ambiente in un ciclo. Ecco un esempio di file .cmd che imposta una variabile d'ambiente a livello di sistema ogni ~ 5 secondi: codice: top setx.exe foo bar ping.exe -n 5 localhost> nul goto top – JohnW

risposta

8

Sembra che questo codice non sia la vera causa del problema. Vedere se una di queste pagine aiuta:

Aggiornamento: fisso url alla prima pagina.

+0

Link utili, eventuali sviluppi per .net 3.x? –

+0

Mi aspetto che .Net 3.x si comporti allo stesso modo di .Net 2.0 in questo caso poiché le DLL di base sono uguali. – David

+0

Sono abbastanza sicuro che questo è il problema ... ora è solo una questione di rintracciare il controllo incriminato che viene creato sul thread sbagliato in qualche modo. –

1

Ho avuto un problema simile e ho trovato il colpevole nel nostro codice.

Tecnica utilizzata: 0. Assicurarsi di Spy ++ che ci sono solo due fili non gestiti con controlli su di loro (WinForms e GDI +):

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

chiamata questo dal thread dell'interfaccia utente su 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. Ricorda ID gestito di Ui Thread in una classe singleton.

  2. Cerca tutti gli UserControls definiti nel nostro codice. Nel costruttore di ciascun controllo, prima di chiamare InitializeComponent(), ho inserito il codice che controlla l'id corrente del thread rispetto all'ID del thread principale. Se non sono uguali, asserisci (falso).

  3. Iscriviti a SystemEvents.UserPreferencesChanging. Debug.Assert (false) in handler: questo succede prima di SystemEvents.UserPreferencesChanged, quindi il debugger si fermerà qui.

  4. Ispezionare elenco di iscritti al SystemEvents nel debugger. Trova un abbonato nel dizionario delle liste di _handles. L'apertura di SynchronizationContext di ogni callback dovrebbe rivelare il problema: lo stesso ID del thread del controllo creato sul thread non dell'interfaccia utente. SystemEvents eseguirà il gestore di eventi su quel thread, deadlocking contro il thread dell'interfaccia utente.

+0

Consigli eccellenti - grazie! –

3

L'altra risposta viene da questo Aaron Lerch. Mi piace molto la parte "breakpoint filtrato sul codice di qualcun altro". Penso che mi avrebbe salvato un paio di giorni.

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

+0

Ho avuto (e continuo ad avere) abbastanza fortuna con esso, in ogni caso. ;) –

Problemi correlati