尝试重新启动线程时发生ThreadStateException

时间:2020-03-05 18:40:04  来源:igfitidea点击:

尝试重新启动线程时,有时会收到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); 
}

因此,有两个问题是这是正确的做事方式吗,有没有办法防止错误发生?

解决方案

回答

抛出ThreadStateException异常是因为我们试图启动一个不在可启动状态下的线程。最有可能的情况是它已经在运行,或者已经完全退出。

可能有几件事可能正在发生。首先,该线程可能已从"运行"转换为"停止请求",但尚未完全停止,因此逻辑不会创建新线程,而我们正在尝试启动一个刚刚运行完毕或者即将执行的线程。完成运行(都不是重新启动的有效状态)。

另一种可能性是线程被中止。中止的线程进入"中止"状态,而不是"已停止"状态,当然也对重启无效。

确实,唯一可以被"重新启动"但仍处于活动状态的线程是被挂起的线程。我们可能要使用以下条件:

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

尽管如果我们要描述问题,但我们尝试更详细地解决,我几乎可以肯定会有更好的解决方案。在我看来,等待一个线程结束只是为了重新启动它似乎并没有那么高效。也许我们只需要某种线程间通信?

约翰。

回答

问题是我们拥有先检查是否应创建新线程对象的代码,以及确定是否可以启动线程对象的另一段代码。由于竞争条件和类似原因,代码可能最终尝试在现有线程对象上调用.Start。考虑到我们没有将详细信息发布在check变量后面,因此无法知道可能触发此行为的原因。

我们应该重新组织代码,以确保仅在新对象上调用.Start。简而言之,我们应该将Start方法放入与创建新线程对象相同的if语句中。

就个人而言,我将尝试重新组织整个代码,从而无需创建另一个线程,而是将代码包装在线程对象内的循环内,以便线程继续运行。