2009-06-18 16 views
5

Ho un problema di debug multithreading piuttosto serio. Ho qualche tipo di problema di temporizzazione quando interagisco con un dispositivo seriale, e ho bisogno di rintracciarlo. Ho tre thread:Debuging filettato in C# e vs2008

  1. Il thread principale per gli aggiornamenti dell'interfaccia utente. L'utente può cambiare un parametro del dispositivo, o molti contemporaneamente, scegliendo un preset.
  2. Il thread di controllo dello stato che richiede di verificare che il dispositivo sia ancora collegato. Se l'utente spegne il dispositivo o il dispositivo stesso viene interagito in modo interessante, i cambiamenti di stato devono riflettersi nell'interfaccia utente.
  3. Il thread che legge la porta seriale in cui il dispositivo risponde.

Il mio problema ha effettivamente a che fare con il debug di questa situazione. Sembra che ogni singola linea che ho in ogni thread debba avere un punto di interruzione per essere debugata; se interrompo un thread, il debugger non passerà attraverso quel thread. Capisco che gli altri thread continueranno ad aggiornare, ma il thread che sto eseguendo non dovrebbe essere normale nel debugger, cioè passare da una riga alla successiva? Quindi, potrei usare la scheda 'discussioni' per passare da un thread all'altro.

Ho detto che sono in WPF perché non so se questo cambierà la situazione; forse lo fa, forse no. Il thread di controllo dello stato fa parte di un controllo dell'interfaccia utente, poiché lo stato deve essere controllato solo mentre l'interfaccia utente è attiva. Questo controllo si trova in una libreria distinta dall'applicazione principale.

+0

Rimosso i riferimenti WPF causano il fatto che non è realmente correlato a WPF - solo un debug di MT generico. –

+0

Sfortunatamente, ho notato che vs2008 ha iniziato a comportarsi in modo molto, molto aggressivo (questo è solo un comportamento problema, altri hanno a che fare con il controllo del codice sorgente e con diverse impostazioni di build) che è accaduto da quando il progetto è migrato a WPF. Quindi l'inclusione, per ogni evenienza. – mmr

risposta

1

Se il tuo codice è single stepping in un modo strano, a volte può essere causato da un semplice file pdb rotto. Un "ricostruisci tutto" sul tuo codice lo rigenererà da zero e curerà tutti questi problemi.

Un'altra cosa da tenere a mente è che l'interruzione di un thread nel debugger può causare tutti i tipi di temporizzazioni insolite che non si vedrebbero in una build di rilascio. Per esempio:

  • la porta seriale sarà sempre continuerà a funzionare (a livello di hardware/driver), mentre si è fermato su un punto di interruzione - la prossima volta che tenta di intensificare il vostro codice, può ricevere un improvviso scoppio enorme di dati. Con richiami asincroni questo può essere "interessante".

  • L'arresto di un thread disturba il normale time -licing in modo che la sincronizzazione thread to thread possa essere rovinata.

7

Quando il debugger si arresta su un punto di interruzione, per impostazione predefinita sospenderà tutti gli altri thread. Ma quando si passa o si continua, vengono ripresi tutti e 3 i thread. Quando si passa attraverso il codice, il debugger imposta fondamentalmente un punto di interruzione temporaneo sulla riga successiva e riprende tutti i thread. Gli altri 2 potrebbero avere la possibilità di correre prima che venga colpito il punto di rottura virtuale.

è possibile congelare gli altri thread durante il debug

Quando sei a un punto di interruzione selezionare Debug | Windows | Discussioni. Seleziona i fili che non ti interessano e fai clic con il pulsante destro del mouse, seleziona Freeze. Questo ti permetterà di concentrarti sull'unico thread che stai attraversando.

+0

ma il mio punto è che non sta colpendo quel punto di interruzione temporaneo; sta semplicemente proseguendo allegramente, non raggiungendo punti di interruzione diversi da quello originale. Voglio che gli altri thread siano in esecuzione; Voglio essere in grado di vedere dove si comportano male. – mmr

+0

Cosa succede quando si interrompe manualmente dopo lo stepping? Si perde da qualche parte in un metodo Win32 o si ferma in un momento successivo nel codice? –

+0

non si ferma mai, continua semplicemente. – mmr

1

Sono con Jason, stepping non mostrerà più la verità.

È davvero meglio strumentare ogni riga di codice con un metodo che incrementa anche un contatore utilizzando Interlocked.Increment e aggiunge il contatore all'output (un file locale è il migliore).

Il contatore è necessario perché l'ordine degli eventi effettivi non è sempre uguale all'ordine di scrittura sul file. Assegna un nome ai thread o usa anche il valore ID nell'output. Io uso MS Excel per aprire il file e colorare tutte le righe a seconda del thread, in questo modo posso vedere le operazioni di interleaving molto chiaramente.

Ho persino scritto un wrapper per bloccare {} quali strumenti quando ogni blocco si accende/spegne.

I problemi di sincronismo sono terrificanti a t-shoot quindi consiglio di non spendere più di quanto ci vorrebbe per il refactoring. A volte è un'indicazione che l'approccio che stai prendendo non è ottimale.

Ricordarsi di utilizzare volatile dove necessario con IO.

Problemi correlati