2009-02-17 8 views
5

Mam aplikację blokującą wątek GUI, a ja użyłem WinDbg wraz z poleceniem "! Clrstack", aby uzyskać ten ślad stosu, ale nie mogę wymyślić gdzie jest problem. Wszystkie te metody wyglądają jak metody ramowe, a żadne nie są moje. Każda pomoc byłaby bardzo cenna. Przepraszam za długie linie:Potrzebujesz pomocy odszyfrować ślad stosu 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

Czy próbuje modyfikować obiekt GUI z wątku, który nie jest właścicielem to? Jeśli tak, możesz uruchomić problem InvokeRequired. –

+0

O ile mi wiadomo, nie wykonuję żadnych operacji krzyżowych. Myślę, że będę miał obszerną recenzję kodu, aby to sprawdzić. –

+0

Jeśli ktokolwiek czytający ten wątek ma do czynienia z tym problemem przerywanym, jednym ze sposobów wymuszenia repro jest ustawienie zmiennej środowiskowej w pętli. Oto przykładowy plik .cmd, który ustawia ogólnosystemową zmienną środowiskową co ~ 5 sekund: kod: top setx.exe foo bar ping.exe -n 5 localhost> nul goto top – JohnW

Odpowiedz

8

Wygląda na to, że ten kod nie jest prawdziwą przyczyną problemu. Zobacz, czy jeden z tych stron pomaga:

Aktualizacja: Poprawiono url do pierwszej strony.

+0

Przydatne linki, wszelkie zmiany dotyczące .net 3.x? –

+0

Spodziewałbym się .Net 3.x zachowywać się tak samo jak .Net 2.0 w tym przypadku, ponieważ podstawowe biblioteki DLL są takie same. – David

+0

Jestem prawie pewien, że to jest problem ... teraz chodzi tylko o wyśledzenie obrażającej kontroli, która jest jakoś tworzona w niewłaściwym wątku. –

1

Miałem podobny problem i znalazłem winnego w naszym kodzie.

technika używana: 0. Upewnij się Spy ++, że istnieją tylko dwie niezarządzani nici z kontroli na nich (WinForms i GDI +):

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

nazywają to z wątku UI na pliku 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. Zapamiętaj zarządzany identyfikator Ui Wątek w klasie singleton.

  2. Wyszukaj wszystkie ustawienia UserControl zdefiniowane w naszym kodzie. W każdym konstruktorze kontrolnym, przed wywołaniem InitializeComponent(), umieściłem kod, który sprawdza bieżący identyfikator wątku względem głównego identyfikatora wątku. Jeśli nie są równe, Assert (fałsz).

  3. Zasubskrybuj SystemEvents.UserPreferencesChanging. Debug.Assert (false) w module obsługi: dzieje się to przed SystemEvents.UserPreferencesChanged, więc debugger, mam nadzieję, zatrzyma się tutaj.

  4. Sprawdź listę subskrybentów SystemEvents w debugerze. Znajdź subskrybenta w słowniku listy dialogów _handles. Otwieranie SynchronizationContext każdego wywołania zwrotnego powinno ujawnić problem: ten sam identyfikator wątku, jak dla formantu utworzonego na wątku innym niż UI. SystemEvents wykona procedurę obsługi zdarzeń w tym wątku, blokując przejście w wątku UI.

+0

Doskonałe wskazówki - dzięki! –