Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Visual Studio offre diversi strumenti ed elementi dell'interfaccia utente che consentono di eseguire il debug di applicazioni multithreading. Questa esercitazione illustra come usare i marcatori di thread, la finestra Stack paralleli, la finestra Osservazione parallela, i punti di interruzione condizionali e i punti di interruzione del filtro. Il completamento di questa esercitazione consente di acquisire familiarità con le funzionalità di Visual Studio per il debug di applicazioni multithreading.
Questi due articoli forniscono informazioni aggiuntive sull'uso di altri strumenti di debug multithreading:
Per usare la barra degli strumenti Percorso di debug e la finestra Thread , vedere Procedura dettagliata: Eseguire il debug di un'applicazione multithreading.
Per un esempio che usa Task (codice gestito) e l'ambiente runtime di concorrenza (C++), consultare Procedura dettagliata: Eseguire il debug di un'applicazione parallela. Per suggerimenti generali sul debug che si applicano alla maggior parte dei tipi di applicazioni multithreading, leggere sia l'articolo che questo.
Il primo passaggio consiste nel creare un progetto di applicazione multithreading.
Creare un progetto di app multithreading
Aprire Visual Studio e creare un nuovo progetto.
Se la finestra iniziale non è aperta, scegliere Finestradi avvio>.
Nella finestra iniziale scegliere Crea un nuovo progetto.
Nella finestra Crea un nuovo progetto immettere o digitare console nella casella di ricerca. Scegliere quindi C#, C++o Visual Basic dall'elenco Linguaggio e quindi scegliere Windows dall'elenco Piattaforma.
Dopo aver applicato i filtri del linguaggio e della piattaforma, scegliere il modello App console per .NET o C++, quindi scegliere Avanti.
Annotazioni
Se non vedi il modello corretto, vai a Strumenti>Recupera strumenti e funzionalità... Verrà aperto il programma di installazione di Visual Studio. Scegliere il carico di lavoro Sviluppo di desktop .NET o Sviluppo di applicazioni desktop con C++ e quindi scegliere Modifica.
Nella finestra Configura il nuovo progetto digitare o immettere MyThreadWalkthroughApp nella casella Nome progetto . Scegliere quindi Avanti o Crea, a qualsiasi opzione disponibile.
Per un progetto .NET Core o .NET 5+, scegliere il framework di destinazione consigliato o .NET 8 e quindi scegliere Crea.
Appare un nuovo progetto console. Dopo aver creato il progetto, viene visualizzato un file di origine. A seconda della lingua scelta, il file di origine potrebbe essere chiamato Program.cs, MyThreadWalkthroughApp.cpp o Module1.vb.
Eliminare il codice visualizzato nel file di origine e sostituirlo con il codice aggiornato seguente. Scegli il frammento di codice appropriato per la configurazione.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }
Scegliere Salva tutto dal menu File.
(solo Visual Basic) In Esplora soluzioni (riquadro destro) fare clic con il pulsante destro del mouse sul nodo del progetto, scegliere Proprietà. Nella scheda Applicazione modificare l'oggetto Startup in Simple.
Eseguire il debug dell'app multithreading
Nell'editor del codice sorgente cercare il frammento di codice seguente:
Fare clic con il pulsante sinistro del mouse sulla barra sinistra dell'istruzione
Thread.Sleep
o, per C++,std::this_thread::sleep_for
per inserire un nuovo punto di interruzione.Nella barra, un cerchio rosso indica che un punto di interruzione è impostato in questa posizione.
Nel menu Debug selezionare Avvia debug (F5).
Visual Studio compila la soluzione, l'app inizia a essere eseguita con il debugger collegato e quindi l'app si arresta in corrispondenza del punto di interruzione.
Nell'editor del codice sorgente individuare la riga contenente il punto di interruzione.
Scoprire il marcatore del thread
Nella barra degli strumenti di debug, selezionare il pulsante Mostra thread nell'origine
.
Premere F11 due volte per far avanzare il debugger.
Guarda la canalina sul lato sinistro della finestra. In questa riga si noti un'icona del marcatore di thread
simile a due fili intrecciati. L'indicatore di thread segnala che un thread è arrestato in questo punto.
Un marcatore di thread può essere parzialmente nascosto da un punto di interruzione.
Posizionare il puntatore sopra l'indicatore del thread. Viene visualizzato un suggerimento dati che indica il nome e il numero ID del thread per ogni thread arrestato. In questo caso, il nome è probabilmente
<noname>
.Selezionare l'indicatore di thread per visualizzare le opzioni disponibili nel menu di scelta rapida.
Visualizzare i percorsi dei thread
Nella finestra Stack paralleli è possibile passare da una vista Thread a una vista Attività (per la programmazione basata su attività) ed è possibile visualizzare le informazioni sullo stack di chiamate per ogni thread. In questa app è possibile usare la visualizzazione Thread.
Aprire la finestra Stack paralleli scegliendo Debug>Windows>Stack paralleli. Dovresti vedere qualcosa di simile al seguente. Le informazioni esatte possono variare a seconda della posizione corrente di ogni thread, dell'hardware e del linguaggio di programmazione.
In questo esempio, da sinistra a destra vengono visualizzate queste informazioni per il codice gestito:
- Il thread corrente (freccia gialla) è entrato
ServerClass.InstanceMethod
. È possibile visualizzare l'ID del thread e lo stack frame di un thread passando il puntatore del mouse suServerClass.InstanceMethod
. - Il thread 31724 è in attesa di un lock posseduto dal thread 20272.
- Il thread principale (visualizzato a sinistra) si è fermato su [Codice Esterno], che puoi visualizzare in dettaglio scegliendo Mostra Codice Esterno.
In questo esempio, da sinistra a destra vengono visualizzate queste informazioni per il codice gestito:
- Il thread principale (lato sinistro) si è fermato su
Thread.Start
, dove il punto di arresto è identificato dall'icona del segna thread.
- Due thread sono entrati nel
ServerClass.InstanceMethod
, uno dei quali è il thread corrente (freccia gialla), mentre l'altro si è fermato inThread.Sleep
. - Un nuovo thread (a destra) è anche in corso, ma viene fermato su
ThreadHelper.ThreadStart
.
- Il thread corrente (freccia gialla) è entrato
Per visualizzare i thread in una visualizzazione elenco, selezionare Debug>Windows>Threads.
In questa visualizzazione è possibile notare facilmente che il thread 20272 è il thread principale e attualmente si trova nel codice esterno, in particolare System.Console.dll.
Annotazioni
Per altre informazioni sull'uso della finestra Thread , vedere Procedura dettagliata: Eseguire il debug di un'applicazione multithreading.
Fare clic con il pulsante destro del mouse sulle voci nella finestra Stack paralleli o Thread per visualizzare le opzioni disponibili nel menu di scelta rapida.
È possibile eseguire varie azioni da questi menu di scelta rapida. Per questa esercitazione, sono esaminati altri dettagli nella finestra Parallel Watch (sezioni successive).
Impostare un monitoraggio su una variabile
Aprire la finestra Controllo parallelo selezionando Debug>Windows>Controllo parallelo>Controllo parallelo 1.
Selezionare la cella in cui viene visualizzato il
<Add Watch>
testo (o la cella di intestazione vuota nella quarta colonna) e immetteredata
.I valori per la variabile di dati per ogni thread vengono visualizzati nella finestra.
Selezionare la cella in cui viene visualizzato il
<Add Watch>
testo (o la cella di intestazione vuota nella quinta colonna) e immetterecount
.I valori per la
count
variabile per ogni thread vengono visualizzati nella finestra. Se non vengono ancora visualizzate molte informazioni, provare a premere F11 alcune volte per avanzare l'esecuzione dei thread nel debugger.Fare clic con il pulsante destro del mouse su una delle righe nella finestra per visualizzare le opzioni disponibili.
Contrassegna e rimuovi il flag dai thread
È possibile contrassegnare i thread per tenere traccia dei thread importanti e ignorare gli altri thread.
Nella finestra Finestra di Controllo Parallelo, tenere premuto il tasto SHIFT e selezionare più righe.
Fare clic con il pulsante destro del mouse e selezionare Contrassegno.
Tutti i thread selezionati vengono contrassegnati. È ora possibile filtrare in modo da visualizzare solo i thread contrassegnati.
Nella finestra Osservazione Parallela, selezionare il pulsante Mostra solo thread contrassegnati
.
Nell'elenco vengono visualizzati solo i thread contrassegnati.
Suggerimento
Dopo aver contrassegnato alcuni thread, è possibile fare clic con il pulsante destro del mouse su una riga di codice nell'editor di codice e scegliere Esegui thread contrassegnati in cursore. Assicurati di scegliere un codice che verrà raggiunto da tutti i thread contrassegnati. Visual Studio sospende i thread nella riga di codice selezionata, semplificando il controllo dell'ordine di esecuzione bloccando e scongelando i thread.
Selezionare di nuovo il pulsante Mostra solo thread contrassegnati per tornare alla modalità Mostra tutti i thread .
Per togliere il flag dai thread, fare clic con il pulsante destro del mouse su uno o più thread contrassegnati nella finestra Parallel Watch e selezionare Rimuovi flag.
Bloccare e sbloccare l'esecuzione del thread
Suggerimento
È possibile congelare e scongelare (sospendere e riprendere) i thread per controllare l'ordine in cui eseguono il lavoro. Questo può aiutarti a risolvere i problemi di concorrenza, come lo stallo e le condizioni di concorrenza.
Nella finestra Osservazione parallela, con tutte le righe selezionate, fare clic con il pulsante destro del mouse e selezionare Blocca.
Nella seconda colonna viene visualizzata un'icona di sospensione per ogni riga. L'icona di pausa indica che il thread è bloccato.
Deselezionare tutte le altre righe selezionando una sola riga.
Fare clic con il pulsante destro del mouse su una riga e scegliere Thaw.
L'icona di pausa viene interrotta in questa riga, che indica che il thread non è più bloccato.
Passare all'editor di codice e premere F11. Viene eseguito solo il thread scongelato.
L'app potrebbe anche avviare alcuni nuovi thread. Tutti i nuovi thread non vengono contrassegnati e non vengono congelati.
Seguire un singolo thread con punti di interruzione condizionali
Può essere utile seguire l'esecuzione di un singolo thread nel debugger. Un modo per farlo consiste nel bloccare i thread a cui non si è interessati. In alcuni scenari potrebbe essere necessario seguire un singolo thread senza bloccare altri thread, ad esempio per riprodurre un particolare bug. Per seguire un thread senza bloccare altri thread, è necessario evitare di interrompere il codice, tranne che nel thread di cui si è interessati. È possibile eseguire questa attività impostando un punto di interruzione condizionale.
È possibile impostare punti di interruzione in condizioni diverse, ad esempio il nome del thread o l'ID del thread. Può essere utile impostare la condizione sui dati noti che sono univoci per ogni thread. Questo approccio è comune durante il debug quando si è più interessati a un determinato valore di dati rispetto a qualsiasi thread specifico.
Fare clic con il pulsante destro del mouse sul punto di interruzione creato in precedenza e selezionare Condizioni.
Nella finestra Impostazioni punto di interruzione immettere
data == 5
per l'espressione condizionale.Suggerimento
Se si è più interessati a un thread specifico, utilizzare un nome di thread o un ID thread come condizione. A tale scopo, nella finestra Impostazioni punto di interruzione selezionare Filtro anziché Espressione condizionale e seguire i suggerimenti per i filtri. È possibile assegnare un nome ai thread nel codice dell'app, perché gli ID thread cambiano quando si riavvia il debugger.
Chiudere la finestra Impostazioni punto di interruzione .
Selezionare il pulsante
per riavviare la sessione di debug.
Si suddivide il codice nel thread in cui il valore della variabile di dati è 5. Nella finestra Monitoraggio Parallelo cercare la freccia gialla che indica il contesto del debugger corrente.
Ora, è possibile scavalcare il codice (F10) ed entrare nel codice (F11) e seguire l'esecuzione del singolo thread.
Finché la condizione del punto di interruzione è univoca per il thread e il debugger non colpisce altri punti di interruzione su altri thread (potresti doverli disabilitare), puoi procedere oltre il codice e inoltrarti nel codice senza passare ad altri thread.
Annotazioni
Quando si fa avanzare il debugger, tutti i thread verranno eseguiti. Tuttavia, il debugger non interromperà l'esecuzione del codice sugli altri thread, a meno che uno di questi non raggiunga un punto di interruzione.