Время от времени я получаю 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);
}
Итак, два вопроса - это правильный способ действий и есть ли способ предотвратить возникновение ошибки?
Проблема в том, что у вас есть код, который сначала проверяет, должен ли он создать новый объект потока, и еще один фрагмент кода, который определяет, нужно ли запускать объект потока. Из-за условий гонки и подобных вещей ваш код может в итоге попытаться вызвать .Start для существующего объекта потока. Учитывая, что вы не публикуете подробности за переменной check , невозможно знать, что может вызвать такое поведение.
Вы должны реорганизовать свой код так, чтобы .Start гарантированно вызывался только для новых объектов. Короче говоря, вы должны поместить метод Start в тот же оператор if, что и тот, который создает новый объект потока.
Лично я попытался бы реорганизовать весь код так, чтобы мне не нужно было создавать другой поток, а обернуть код внутри объекта потока внутри цикла, чтобы поток просто продолжал работать.
Выдается исключение ThreadStateException, поскольку вы пытаетесь запустить поток, который не находится в состоянии запуска. Наиболее вероятные ситуации могут быть: он уже запущен или полностью завершен.
Есть потенциально пара вещей, которые могут происходить. Во-первых, поток, возможно, перешел из Running в StopRequested, который еще не полностью остановлен, поэтому ваша логика не создает новый поток, и вы пытаетесь запустить поток, который только что завершил работу или собирается завершить завершите работу (ни одно из которых не является допустимым для перезапуска).
Другая возможность состоит в том, что поток был прерван. Прерванные потоки переходят в состояние «Прервано», а не в состояние «Остановлено» и, разумеется, также недопустимы для перезапуска.
Действительно, единственный вид потока, который все еще жив, который можно «перезапустить», - это тот, который приостановлен. Вы можете использовать это условие вместо:
if (this.mThread == null || this.mThread.ThreadState != ThreadState.Suspended)
Возможно, что поток находится в более чем одном состоянии одновременно, поэтому свойство ThreadState является фактически битовой картой возможных состояний. Поэтому проверка на равенство только с одним государством не даст вам правильного результата. Вам нужно будет сделать что-то вроде:
if((mThread.ThreadState & ThreadState.Running) != 0)
Тем не менее, проверка состояния потока неправильно делать что-либо. Я не совсем понимаю, чего вы пытаетесь достичь, но я предполагаю, что вы ожидаете завершения потока, прежде чем перезапустить его. В этом случае вы должны сделать:
mThread.Join();
mThread = new Thread(new ParameterizedThreadStart(Monitor));
if(check)
mThread.Start(60000);
else
mThread.Start(0);
Хотя если вы опишите проблему, которую вы пытаетесь решить более подробно, я почти уверен, что будет лучшее решение. Ожидание завершения потока, чтобы просто перезапустить его, не кажется мне эффективным. Может быть, вам просто нужна какая-то связь между потоками?
Джон.