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

StackOverflow https://stackoverflow.com/questions/13170

Вопрос

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Поток может находиться в нескольких состояниях одновременно, поэтому свойство 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 генерируется, потому что вы пытаетесь запустить поток, который не находится в состоянии startable.Наиболее вероятными ситуациями было бы то, что он уже запущен или что он полностью завершен.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top