ThreadStateException возникает при попытке перезапустить поток - PullRequest
6 голосов
/ 16 августа 2008

Время от времени я получаю исключение 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 ]

6 голосов
/ 16 августа 2008

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

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

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

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

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

Джон.

3 голосов
/ 16 августа 2008

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

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

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

1 голос
/ 16 августа 2008

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...