Come eseguire il debug di un singolo thread in Visual Studio?


254

Ho una soluzione con alcuni progetti. Esistono diversi punti di interruzione in diversi progetti. Voglio tracciare il primo thread colpito uno di questi punti di interruzione e continuare a tracciare quel singolo thread nonostante altri thread entrino negli stessi blocchi di codice.

So che questo è possibile attraverso la definizione di una condizione sul punto di interruzione, ovvero thread name = ... o thread Id = ... ma il mio caso è un'applicazione ASP.NET pesantemente caricata e non appena mi collego a w3wp.exemolti le discussioni colpiranno i punti di interruzione. Ho bisogno di qualcosa come un ThreadLocal<break-point>.

È possibile? Se é cosi, come?


7
@Paolo: questa applicazione web funziona come il cuore di una grande web farm e la situazione buggy è impossibile da imitare negli scenari di test.
Xaqron,

Per VS 2019 forse dovresti provare questo: stackoverflow.com/a/61868591/8579563
Gozo

Risposte:


151

Congelare / scongelare i thread è un modo errato perché altri thread non eseguono alcun codice.

Il modo più corretto e utilizzabile è:

  1. Premi Ctrl + A nella finestra dei punti di interruzione (seleziona tutti i punti di interruzione).
  2. Fare clic destro e selezionare "Filtro ...".
  3. Immettere "ThreadId = (id thread corrente)".

In Visual Studio 2015 e versioni successive, il processo è simile:

  1. Premi Ctrl + A nella finestra dei punti di interruzione (seleziona tutti i punti di interruzione).
  2. Fare clic destro e selezionare "Impostazioni ...".
  3. Seleziona "Condizioni" e seleziona "Filtro" nel menu a discesa
  4. Immettere "ThreadId = (id thread corrente)".

Quindi tutti i thread vengono eseguiti, ma il debugger colpisce solo sul thread corrente.


51
Questo impedisce al comando debugger "Step" di inserire altri thread? Questo è stato un grosso problema che ho avuto. Sto esaminando il mio thread e all'improvviso mi trovo in una porzione di codice completamente non correlata. Non sviluppo più in Visual Studio, quindi non riesco a testare.
Matt Faus,

8
Fare clic con il tasto destro nella finestra dei punti di interruzione non ha alcun comando "filtro" ... e come si fa a trovare l'ID thread corrente? - Stai andando alla finestra immediata e digitando System.Threading.Thread.CurrentThread.ManagedThreadIdo qualcosa del genere?
BrainSlugs83

5
Nel mio VS (2015, Community Edition) non è possibile modificare le impostazioni di più punti di interruzione contemporaneamente. Pertanto, il filtro può essere impostato solo uno per uno.
robert4

5
Ho avuto questo problema per sempre, e potrei giurare nel mio ultimo lavoro che ho trovato un'impostazione che ha fatto funzionare Visual Studio come un'eclissi in cui ti saresti attaccato al thread con cui stavi lavorando, ma non riesco a trovarlo o nessun riferimento ad esso. Sto cominciando a chiedermi se l'ho sognato.
stu,

7
-1 perché ciò consente solo i punti di interruzione, ma non il debug effettivo: il passaggio / passaggio non funziona in questo modo per il debug di un singolo thread.
Serge Rogatch,

338

Ecco cosa ho fatto:

  1. Stabilisci un punto di interruzione condizionale che sapevo colpirebbe solo il thread che stavo cercando.

  2. Una volta che il punto di interruzione raggiunge e sei nel thread desiderato, nella finestra Discussioni di Visual Studio (durante il debug, Debug -> Windows -> Thread), Ctrl+ A(per selezionare tutti i thread), quindi Ctrl+ fai clic sul thread in cui ti trovi attualmente . Dovresti avere tutti i thread tranne quello di cui vuoi eseguire il debug selezionato.

  3. Fare clic con il tasto destro del mouse e selezionare "Blocca".

Ora, Visual Studio passerà attraverso il thread scongelato. Sembra essere molto più lento quando lo fa, presumibilmente perché deve passare attraverso tutti i thread congelati, ma ha portato un po 'di buonsenso al mio debug multi-thread.


1
Questo non funziona per me in un contesto in cui ho circa 8 attività in esecuzione in thread diversi. Congelo tutti gli altri thread e "passo oltre", ma l'IDE si blocca per un po ', quindi salta comunque su un altro thread.
Meta-Knight,

3
@Diego: non sto più lavorando al progetto, ma se congelerà tutti i thread tranne uno, cambierà lo scenario che ha causato l'errore, poiché i thread erano complementari in una situazione buggy. Anche se questa è una soluzione elegante, sembra che questa funzione dovrebbe essere integrata in VS.
Xaqron,

3
@ Meta-Knight Dovresti congelare tutti i thread tranne il thread principale. Se farai come questo IDE non verrà congelato
Alex Zhukovskiy il

15

Ho appena rilasciato un'estensione di Visual Studio 2010+ che fa esattamente quello che stai cercando. Ed è gratuito :).

Presentazione

Questa estensione di Visual Studio aggiunge due scorciatoie e pulsanti della barra degli strumenti per consentire agli sviluppatori di concentrarsi facilmente su singoli thread durante il debug di applicazioni multi-thread.

Riduce drasticamente la necessità di accedere manualmente alla finestra Thread per congelare / scongelare tutti i thread tranne quello che deve essere seguito, e quindi aiuta a migliorare la produttività.

Caratteristiche

Limitare ulteriori esecuzioni solo al thread corrente. Congelerà tutti gli altri thread. Scorciatoia: tasto CTRL + T + T o fiocco di neve. Passa al thread singolo successivo (in base all'ID). Cambierà il thread corrente e congelerà tutti gli altri thread. Scorciatoia: CTRL + T + J o pulsante Avanti.

Dai un'occhiata qui sulla Galleria , sulla pagina ufficiale o sul repository Github .


Quale versione di VS stai usando?
Erwin Mayer,

Ho installato l'estensione, ma non sono riuscito a farlo funzionare (per il mio progetto attuale, utilizzo VS2010). [A proposito, ciò che pensavo fosse un problema con l'attivazione dei thread si verifica solo quando vengono creati i thread, è probabilmente un comportamento standard, quindi ho rimosso il mio commento precedente].
cancella il

3
Ho intenzione di dare un'occhiata. Potresti essere l'unica persona al mondo che ha tentato di risolvere uno dei maggiori errori di debug di Microsoft.
stu,

ahimè, non verrà installato su vs2012. Hai una versione più recente o vuoi condividere il codice sorgente in modo che io possa costruirlo da solo?
stu,

@stu Il codice sorgente è su Codeplex qui: singlethread.codeplex.com dovrebbe funzionare su VS 2012 e VS 2013 ma non l'ho aggiornato (nessuno lo ha richiesto e non ne ho avuto la necessità). Se riesci a farlo funzionare facilmente con VS 2012+ e fai un commit su Codeplex, posso anche spingerlo sulla Galleria.
Erwin Mayer,

13

Se vengono generati più thread come per un'applicazione Web, le risposte di @MattFaus non funzioneranno. quello che ho fatto invece è il seguente

  • Impostare un punto di interruzione per interrompere il thread nella funzione che desidero.
  • Una volta che il thread arriva al punto di interruzione e viene messo in pausa, rimuovo il punto di interruzione e continuo il debug utilizzando F8, F10 e F11, in modo che gli altri thread possano essere eseguiti.

Dopo aver letto tutte le risposte migliori, questa soluzione ha funzionato per me.
Swanand Pangam,

9

Un approccio leggermente diverso che ho usato:

  1. Crea un breakpoint normale e lascia che venga colpito
  2. Cerca nella finestra dei thread l'ID thread gestito di cui stai eseguendo il debug
  3. Fare clic con il tasto destro del mouse sul punto di interruzione nella finestra dei punti di interruzione e nel filtro di selezione
  4. Immettere ThreadId = xxx dove xxx è l'ID thread da 2
  5. Ora puoi eseguire il debug senza arrestare altri thread e senza che colpiscano il tuo punto di interruzione

Ciò presuppone che tu abbia il tempo di fare quanto sopra prima che un secondo thread raggiunga il tuo punto di interruzione. In caso contrario e altri thread raggiungono il punto di interruzione prima di aver fatto quanto sopra, è possibile fare clic con il pulsante destro del mouse nella finestra dei thread e scegliere il blocco.


3
+1. "Questo presuppone che tu abbia tempo ... prima che un secondo thread raggiunga il tuo punto di interruzione". Avvolgo un punto e virgola in un lucchetto e metto un punto di interruzione sul punto e virgola. Quando il breakpoint viene colpito per la prima volta, disabilito il breakpoint. Nessun altro thread può entrare a causa del blocco. lock(m_someObject) { ; }
bluedog,

Per salvarti un Google, la finestra dei thread si trova in Debug> Windows> Thread.
Gabe,

2

In VS 2019:

  1. Impostare un punto di interruzione da qualche parte.
  2. Premi F5 (Continua) finché non arriva il tuo thread.
  3. Fare clic sul punto di interruzione per rimuoverlo.
  4. Puoi passare il thread con F10 o F11.

Funziona anche con VS2015!
prehistoricpenguin

1

Suggerirei di aggiungere un'altra istanza dell'applicazione sul server live, sullo stesso hardware o su una nuova macchina (cluster) e quindi eseguire il debug solo di quell'istanza. Non aggiungerei un punto di interruzione nel trigger degli utenti di codice. Se questa non è un'opzione, aggiungerei più traccia.

Tuttavia, se ciò è assolutamente necessario e hai bisogno di una statistica della soluzione, sono sicuro che potresti aggiungere un punto di interruzione che si interrompe solo se la richiesta proviene dal tuo indirizzo IP. Lo faresti aggiungendo un breakpoint condizionale che ispeziona HttpContext.Request.UserHostAddress. Si noti tuttavia che ciò rallenta notevolmente l'applicazione.


Questo è quello che ho provato. Il problema è che questa istanza non funziona sullo stesso dominio (in esecuzione su IP o un altro dominio) e questo porta a molti problemi di certificazione (SSL, WCF, ...) e anche a basso carico la situazione buggy non si verifica mai!
Xaqron,

Siamo spiacenti, non sono sicuro di quale di questi hai provato, hai provato il breakpoint condizionale?
steinar

Sì, li ho nominati in base al loro ID gestito per garantire l'unicità. Quindi è difficile indovinare quale ID è assegnato e impostare la condizione in base a un'ipotesi. A volte l'ipotesi è vicina e a volte ci vuole molto tempo per capire il filo.
Xaqron,

1

Se non vuoi interrompere tutti gli altri thread (forse stai collegando il debugger di Visual Studio a un'applicazione in esecuzione che deve rispondere alle richieste), puoi utilizzare una macro che crea e rimuove automaticamente i punti di interruzione.

Questo è suggerito in una risposta alla domanda Stack Overflow "Step over" durante il debug di programmi multithread in Visual Studio .

Tuttavia, il collegamento spiega solo come eseguire il debug riga per riga. Ti suggerisco di modificare la macro (se ti senti a tuo agio) per farlo modificare tutti i punti di interruzione (ad esempio in un determinato intervallo di linee) per interrompere solo il thread corrente.


1

Penso che questo sia leggermente diverso in Visual Studio 2015. Hanno cambiato alcune cose nei punti di interruzione, ma ecco come applicare la risposta accettata da hzdbyte (sopra):

Sul punto di interruzione nel margine di codifica, fare clic con il pulsante destro del mouse> Condizioni> Cambia da "Espressione condizionale" a "Filtro". Ciò consente quindi di filtrare per ThreadId.

In alternativa, sul punto di interruzione nella finestra Punti di interruzione, fare clic con il pulsante destro del mouse> Impostazioni> selezionare la casella Condizioni ed eseguire quanto sopra.


1

Imposta una condizione di breakpoint facendo clic con il tasto destro sulla barra laterale della linea. Seleziona "Condizione" e inserisci quanto segue tra virgolette:

System.Threading.Thread.CurrentThread.Name == "name_of_your_thread"

In alternativa puoi fare lo stesso ottenendo il "Managed ID" del thread dalla finestra "Thread" e usare:

System.Threading.Thread.CurrentThread.ManagedThreadId == your_managed_thread_id

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.