背景:
在调试应用程序时,我遇到了这个函数
boolean IsThreadGood(Thread t)
{
return t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin;
}
我认为这是一个错误,因为在return语句中发生的逻辑比较不是原子的,因此我认为Thread t可以在表达式执行时改变状态。为了检查这个想法,我将代码更改为以下代码,以便我可以放置断点:
bool IsThreadGood(Thread t)
{
if (t.IsAlive)
{
if (t.ThreadState == ThreadState.Running)
{
return true;
}
if (t.ThreadState == ThreadState.WaitSleepJoin)
{
return true;
}
}
return false;
}
我在内部if语句上放置了断点,很快就看到了我怀疑的内容。当代码到达第一个断点时,线程t的ThreadState为WaitSleepJoin,当我将代码转移到下一个if语句时,线程t已经切换状态并且线程状态为Running,因此两个测试都失败并且当方法返回false时应该回归真实。
我的问题:
我怎样才能以线程安全的方式检查来自另一个线程的线程的状态?
我的想法和我研究的内容:
如果我能使声明成为原子,那就行了。我用Google搜索了一些诸如“如何在c#中创建一个原子语句”并得到了很多涉及锁的结果 - 而不是我想要的东西,因为据我所知,锁不会使代码成为原子。
如果我可以从执行该方法的线程挂起Thread t,那么我可以安全地检查它的状态。我在这里找到的是过时的功能Suspend and Resume。 Microsoft强烈建议不要使用这些。
以某种方式更改线程t以实现同步。不是一种选择。代码是可重用的代码,已被不同的客户端以不同的方式重用,而Thread t是客户端代码。无法更改所有客户。
我不是多线程大师,所以如果我的任何假设不正确或者我对多线程的理解不正确,请随时指出。
答案 0 :(得分:3)
我很确定状态为Running
或WaitSleepJoin
的线程不能无效。所以你可以得到状态(这是一个原子操作),然后检查这两个值:
boolean IsThreadGood(Thread t)
{
ThreadState state = t.ThreadState;
return state == ThreadState.Running || state == ThreadState.WaitSleepJoin;
}
请注意,the documentation明确指出您应该仅将线程状态用于调试目的,而不是用于同步:
线程状态仅在调试方案中有用。您的代码永远不应该使用线程状态来同步线程的活动。
由于您对原子操作感兴趣,我怀疑您是否希望将其用于调试目的(否则您不需要关心它是否超精确)。所以你应该考虑以不同的方式解决你的实际问题。
答案 1 :(得分:1)
这可能无法正常工作。线程可能处于最后一条指令,您的支票将错过接近并保证退出。线程必须与您合作。您需要在更高级别进行同步。我无法建议如何,因为我不知道应用程序的功能。提出一个包含详细信息和代码的新问题。
注意,t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin
错过了||
运算符周围的大括号。并不重要,因为必须抛弃此代码。
state == ThreadState.WaitSleepJoin
应该完成什么?这种状态可能会发生虚假,因为许多库可能会进入该状态。这一切似乎都是假的。
作为一种解决方法,您可以实现一个监视程序线程:
while (true)
DetectExit();
Sleep(100);
答案 2 :(得分:0)
方法Thread.Join(int millisecondsTimeout)
可用于安全地测试线程是否已完成。当线程不再处于活动状态时,它返回true。
// 0 == don't wait.
if (thread.Join(0))
{
// remove thread from the list
}
出于显而易见的原因,应该从另一个线程调用它。