Исключение ThreadStateException возникает при попытке перезапустить поток

Время от времени я получаю исключение System.Threading.ThreadStateException при попытке перезапустить поток. Рассматриваемый код выглядит следующим образом:

// 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); 
}

Итак, два вопроса - это правильный способ делать что-то, и есть ли способ предотвратить возникновение ошибки?

Ответов (3)

Решение

Проблема в том, что у вас есть код, который сначала проверяет, должен ли он создавать новый объект потока, и другой фрагмент кода, который определяет, нужно ли запускать объект потока. Из-за состояния гонки и подобных вещей ваш код может в конечном итоге попытаться вызвать .Start для существующего объекта потока. Учитывая, что вы не публикуете подробности проверочной переменной, невозможно узнать, что может вызвать такое поведение.

Вам следует реорганизовать свой код так, чтобы гарантированно вызывать .Start только для новых объектов. Короче говоря, вы должны поместить метод Start в тот же оператор if, что и тот, который создает новый объект потока.

Лично я бы попытался реорганизовать весь код, чтобы мне не нужно было создавать другой поток, а обернуть код внутри объекта потока внутри цикла, чтобы поток просто продолжал работать.

Поток может одновременно находиться в нескольких состояниях, поэтому свойство ThreadState на самом деле является битовой картой возможных состояний. Таким образом, проверка на равенство только с одним состоянием не даст вам правильного результата. Вам нужно будет сделать что-то вроде:

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

Однако проверка состояния потока - это неправильно. Я не совсем понимаю, чего вы пытаетесь достичь, но я предполагаю, что вы ждете завершения потока перед его перезапуском. В этом случае вам следует сделать:

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

Хотя, если вы опишете проблему, которую пытаетесь решить, более подробно, я почти уверен, что будет лучшее решение. Ожидание завершения потока только для того, чтобы снова его перезапустить, мне не кажется таким эффективным. Возможно, вам просто нужно какое-то межпотоковое общение?

Джон.

Возникает исключение ThreadStateException, потому что вы пытаетесь запустить поток, который не находится в состоянии запуска. Наиболее вероятны ситуации, когда он уже запущен или полностью завершен.

Потенциально может произойти пара вещей. Во-первых, поток, возможно, перешел от выполнения к StopRequested, который еще не остановлен полностью, поэтому ваша логика не создает новый поток, и вы пытаетесь запустить поток, который только что завершил работу или вот-вот завершится. завершить работу (ни одно из этих состояний не является допустимым для перезапуска).

Другая возможность состоит в том, что поток был прерван. Прерванные потоки переходят в состояние «Прервано», а не в состояние «Остановлен», и, конечно же, они также не подходят для перезапуска.

На самом деле, единственный живой поток, который можно «перезапустить», - это приостановленный. Вместо этого вы можете использовать это условие:

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