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

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

16.08.2008 15:24:19
3 ОТВЕТА
РЕШЕНИЕ

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

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

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

3
16.08.2008 17:56:47

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

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

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

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

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

1
16.08.2008 16:18:58

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

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

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

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

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

Джон.

6
16.08.2008 16:25:07