2013-11-23 26 views
6

Ho una domanda di console C# .NET che invia un'email utilizzando SmtpClient.Il processo o il thread è stato modificato dall'ultimo passaggio (Visual Studio)

Sono sperimenta il seguente comportamento nel codice riportato di seguito:

  1. Impostare un punto di interruzione da qualche parte sopra la linea 35
  2. Hit il punto di rottura, passo attraverso la linea 30, 32, ecc
  3. prima che colpisce la linea 35, salta indietro fino alla linea 28 di nuovo
  4. ad un certo punto, ho la "il processo o il thread è cambiato da ultimo passo" messaggio
  5. Il salto intorno sembra casuale

The process or thread has changed since last step screen shot

Perché il mio punto di rottura salto in giro?

Che cosa significa questo messaggio?

C'è qualcosa che non va nel mio codice?

(Here's another similar question on Stackoverflow. Probabilmente la stessa cosa, ma è ASP.NET) punta


Per Hans passants di seguito.

Questa versione ancora permessi race condition: Toggle Timer.AutoReset proprietà in gestore di eventi di mio timer per evitare la re-entrancy mentre il codice è in esecuzione.

private void OnTimerElapsed(object source, ElapsedEventArgs e) 
{ 
    timer.AutoReset = false; // prevent another Elapsed event 
    MyClass.SendMail(smtpServer, account, password); // do stuff 
    timer.AutoReset = true; // allow another Elapsed event 
} 

versione finale: Inizializzare il timer con AutoReset già impostato su false, quindi chiamare Timer.Start() di nuovo alla fine del vostro gestore di eventi trascorso.

public void Start() 
{ 
    timer = new Timer(checkInterval); 
    timer.Elapsed += new ElapsedEventHandler(OnTimerElapsed); 
    timer.AutoReset = false; // prevent race condition 
    timer.Start(); 
} 

private void OnTimerElapsed(object source, ElapsedEventArgs e) 
{ 
    bool exceptionIsNasty = false; 
    try { 
     MyClass.SendMail(smtpServer, account, password); // do stuff 
    } 
    catch (Exception ex) { 
     // Log exception, set exceptionIsNasty to true if the mailing should be stopped 
     //... 
    } 
    finally { 
     if (!exceptionIsNasty) timer.Start(); // allow another Elapsed event 
    } 
} 

risposta

7

Hai più di un thread che esegue lo stesso metodo e tutti hanno raggiunto lo stesso punto di interruzione. Quando si continua a fare un passo, il debugger non può indovinare con precisione quale thread per cui dovrebbe mostrare lo stato. Quindi ricevi un avvertimento che stai guardando lo stato di una discussione diversa. I valori delle variabili locali possono essere diversi. Come è ovvio il luogo dell'esecuzione, la ragione per cui l'evidenziazione cambia.

Chiaramente questo può rendere più difficile il debug. Vuoi evitare questo se stai ancora ricevendo bug dal codice, inizia solo un thread. Oltre a ciò, una soluzione temporanea consiste nell'utilizzare Debug + Windows + Threads, fare clic con il pulsante destro del mouse su uno dei thread e selezionare Freeze. Non dimenticare di sbloccare nuovamente.

+0

Questo metodo è 'statico', ma ho ragione nel ritenere che la stessa cosa sarebbe accaduta anche se non lo fosse, e ho dovuto creare una nuova istanza dell'oggetto ogni volta che volevo inviare una e-mail?Inoltre, ho ragione a supporre che il motivo per cui ho più thread che eseguono lo stesso codice è perché ho un evento che si attiva ogni 1 secondo, e ogni volta che * lentamente * prendo F10, il metodo viene chiamato di nuovo da quell'evento? – JohnB

+1

Se è statico o meno non è rilevante. Usare un timer per chiamare questo metodo è un ottimo modo per entrare in questo tipo di problemi. Se l'invio di un messaggio di posta elettronica richiede più di 1 secondo, verrà generato un * altro * thread avviato dal timer per eseguire il metodo. Molto malsano. E inevitabile quando monti il ​​metodo, che ovviamente richiede sempre più di un secondo. Prendi in considerazione la saggezza di mandare * ottantamila * email al giorno. Evitare questa riaccranatura impostando la proprietà AutoReset del timer su false. –

+0

Grazie per il suggerimento! Ho implementato correttamente il tuo suggerimento? (Vedere aggiornamento alla mia domanda sopra.) * A proposito, l'intervallo del timer di 1 secondo era solo a scopo di test. Nel mondo reale, il mio timer è molto meno frequente. * – JohnB

Problemi correlati