Domanda

Di tanto in tanto ricevo un'eccezione System.Threading.ThreadStateException quando tento di riavviare un thread.Il codice in questione è il seguente:

// Make sure the thread is done stopping
while (this.mThread.ThreadState == ThreadState.Running)
{ 
    Thread.Sleep(0);
}
// Respawn a thread if the current one is stopped or doesn't exist
if (this.mThread == null || this.mThread.ThreadState == ThreadState.Stopped)
{ 
    this.mThread = new Thread(new ParameterizedThreadStart(Monitor)); }
// Start the thread
if (check)
{ 
    this.mThread.Start(60000); 
}
else
{   
    this.mThread.Start(0); 
}

Quindi due domande: è questo il modo corretto di fare le cose e lo è, esiste un modo per evitare che si verifichi l'errore?

È stato utile?

Soluzione

Il problema è che hai un codice che controlla prima se deve creare un nuovo oggetto thread e un altro pezzo di codice che determina se avviare l'oggetto thread.A causa delle condizioni di competizione e cose simili, il tuo codice potrebbe finire per tentare di chiamare .Start su un oggetto thread esistente.Considerando che non pubblichi i dettagli dietro il controllo variabile, è impossibile sapere cosa potrebbe innescare questo comportamento.

Dovresti riorganizzare il tuo codice in modo che .Start sia garantito per essere chiamato solo su nuovi oggetti.In breve, dovresti inserire il metodo Start nella stessa istruzione if di quella che crea un nuovo oggetto thread.

Personalmente, proverei a riorganizzare l'intero codice in modo da non aver bisogno di creare un altro thread, ma avvolgerei il codice all'interno dell'oggetto thread all'interno di un ciclo in modo che il thread continui ad andare avanti.

Altri suggerimenti

È possibile che un thread si trovi in ​​più di uno stato contemporaneamente, pertanto la proprietà ThreadState è in realtà una bitmap di possibili stati.Quindi testare l'uguaglianza con un solo stato non ti darà il risultato giusto.Dovresti fare qualcosa del tipo:

if((mThread.ThreadState & ThreadState.Running) != 0)

Tuttavia, controllare lo stato del thread è sbagliato fare qualsiasi cosa.Non è del tutto chiaro cosa stai cercando di ottenere, ma immagino che tu stia aspettando che un thread termini prima di riavviarlo.In tal caso dovresti fare:

mThread.Join();
mThread = new Thread(new ParameterizedThreadStart(Monitor));
if(check)
    mThread.Start(60000);
else
    mThread.Start(0);

Tuttavia, se descrivi il problema che stai cercando di risolvere in modo più dettagliato, sono quasi certo che ci sarà una soluzione migliore.Aspettare che un thread finisca solo per riavviarlo di nuovo non mi sembra così efficiente.Forse hai solo bisogno di una sorta di comunicazione tra thread?

John.

Viene generata un'eccezione ThreadStateException perché stai tentando di avviare un thread che non è in uno stato avviabile.Le situazioni più probabili sarebbero che sia già in esecuzione o che sia completamente uscito.

Ci sono potenzialmente un paio di cose che potrebbero accadere.Il primo è che il thread potrebbe essere passato da Running a StopRequested, che non è ancora stato completamente interrotto, quindi la tua logica non crea un nuovo thread e stai tentando di avviare un thread che ha appena terminato l'esecuzione o sta per farlo terminare l'esecuzione (nessuno dei quali è uno stato valido per il riavvio).

L'altra possibilità è che il thread sia stato interrotto.I thread interrotti passano allo stato Aborted, non allo stato Stopped e ovviamente non sono validi nemmeno per il riavvio.

In realtà, l'unico tipo di thread ancora vivo che può essere "riavviato" è quello sospeso.Potresti invece utilizzare questo condizionale:

if (this.mThread == null || this.mThread.ThreadState != ThreadState.Suspended)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top