2016-05-06 5 views
4

Ich habe eine native C++ - Anwendung unter VS2014 SP2, die eine Menge von Multi-Threading mit meiner eigenen Thread-Pool-Klasse verwendet. In der Regel werden in der Anwendung> 32 Threads gleichzeitig ausgeführt, von denen die meisten die meiste Zeit inaktiv sind. Gibt es irgendeinen Weg im Debugger zu sehen, welche Threads in der Thread-Ansicht sich im Leerlauf befinden (d. H. In einer Schlaffunktion), wie dies gegenwärtig der Fall ist, bringt der Debugger typischerweise den schlafenden Teil eines inaktiven Threads zurück;Debugging Multithread-C++ - Anwendung mit großen Thread-Pool

UINT _cdecl MyThreadFunc(LPVOID pParam) 
{ 
    CMyThreadSlot *pThreadInfo = (CMyThreadSlot*)pParam; 
    while (pThreadInfo->m_pManager->m_Active) 
    { 
     try 
     { 
      if (pThreadInfo->m_pActivity) 
      { 
       pThreadInfo->m_pActivity->Execute(); 
       pThreadInfo->m_pActivity = NULL; 
      } 
      else 
       Sleep(50); <-- breaking execution ends up here 
     } 
     catch (CUserException* e) 
     { 
      e->Delete(); 
      if (pThreadInfo->m_pActivity) 
       if (pThreadInfo->m_pActivity->m_pThreadGroup) 
        pThreadInfo->m_pActivity->m_pThreadGroup->m_ExceptionThrown = TRUE; 
     } 
    } 
    return CMyThreadManager::ExitOk; 
} 

Wenn ich hier am Ende nach dem Aufschlagen, ich habe zur Zeit durch den Call-Stack für jeden Thread schleppen, um zu sehen, was tatsächlich ausgeführt wurde, die schmerzhaft sein kann. Selbst wenn ich in anderen Code einbringe, möchte ich immer noch wissen, welche anderen Threads nicht schlafen und was sie tun.

Edit: Ok, klobig genug Lösung, aber Process Explorer Anheizen, direkt auf meiner laufenden Anwendung klicken, Eigenschaften Fäden Auswahl ermöglicht es mir, Themen von CPU-Auslastung zu sortieren, kann die Thread-ID des aktiven Threads dann Figur mich finden heraus, welche Threads verwendet werden. Hauptfehler ist, dass dies vor dem Brechen der laufenden App getan werden muss.

+0

Nichts mit Ihrem Problem zu tun, aber ich frage mich, warum verwenden Sie 'catch (CUserException * e)' statt nur 'catch (CUserException const & e)'. Welche Vorteile bringt der Zeiger für Ihren Fall? – Nawaz

+1

@Nawaz, kein Grund, anders als ein trauriger alter MFC-Hack aus der Dinosaurier-Ära;) –

+1

Wenn Sie einen eindeutigen Namen für die Threads-Einstiegspunkte verwenden, dann könnte das der Anfang Ihres Debugging in die richtige Richtung sein. Aber dann erscheint es sehr peinlich, verschiedene Einstiegspunkte zu schreiben, wenn alle dasselbe tun. Eine Lösung könnte der Einstiegspunkt als Vorlage sein. Ich habe diese Technik in der Vergangenheit verwendet, um für jeden Thread-Einstiegspunkt einen anderen Namen zu generieren. – Nawaz

Antwort

3

Ich habe es herausgefunden. Trick bestand darin, Threads mit unter normaler Priorität zu initialisieren, sie beim Ausführen auf normal zu setzen und danach auf unter Normal zurückzusetzen. In der Thread-Ansicht des Debuggers erhalten Sie nach der Sortierung nach Priorität Ihre aktiven Threads. So vom vorherigen Code, Thread wird als

und früheren Code wie folgt geändert;

 if (pThreadInfo->m_pActivity) 
     { 
      SetThreadPriority(pThreadInfo->m_hThread, THREAD_PRIORITY_NORMAL); 
      pThreadInfo->m_pActivity->Execute(); 
      SetThreadPriority(pThreadInfo->m_hThread, THREAD_PRIORITY_BELOW_NORMAL); 
      pThreadInfo->m_pActivity = NULL; 
     } 

Edit: Wenn Sie nicht Priorität ändern wollte, sieht es aus wie Sie es auch durch thread naming genug handlich tun konnte.