Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以线程安全的方式检查一个线程和另一个线程的状态?_C#_Multithreading - Fatal编程技术网

C# 如何以线程安全的方式检查一个线程和另一个线程的状态?

C# 如何以线程安全的方式检查一个线程和另一个线程的状态?,c#,multithreading,C#,Multithreading,背景: 在调试应用程序时,我遇到了这个函数 boolean IsThreadGood(Thread t) { return t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin; } 我认为这是一个bug,因为return语句中发生的逻辑比较不是原子的,因此我认为线程t可能在执行表达式时改变状态。为了验证这一想法,我将代码更改为以下代

背景:

在调试应用程序时,我遇到了这个函数

boolean IsThreadGood(Thread t)
{
    return t.IsAlive && t.ThreadState == ThreadState.Running || t.ThreadState == ThreadState.WaitSleepJoin;
}
我认为这是一个bug,因为return语句中发生的逻辑比较不是原子的,因此我认为线程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的状态已切换,ThreadState为Running,因此测试失败,并在返回true时从方法返回false

我的问题:

如何以线程安全的方式从另一个线程检查线程的状态

我的想法和我的研究:

  • 如果我能使这个陈述原子化,它就会起作用。我在谷歌上搜索了一些东西,比如“如何在c#中使语句原子化”,得到了很多关于锁的结果——这不是我想要的,因为据我所知,锁不会使代码原子化

  • 如果我可以从执行该方法的线程中挂起线程t,那么我就可以安全地检查它的状态。我在这里发现的是过时的函数Suspend和Resume。Microsoft强烈建议不要使用这些

  • 以某种方式更改线程t以实现同步。没有选择。代码是可重用代码,不同的客户端以不同的方式重用了该代码,线程t是客户端代码。无法更改所有客户端


  • 我不是多线程专家,因此如果我的任何假设不正确或我对多线程的理解不正确,请随时指出。

    我非常确定,状态为运行的线程或状态为WaitSleepJoin的线程不可能处于活动状态。因此,您可以只获取状态(这是一个原子操作),然后对照这两个值进行检查:

    boolean IsThreadGood(Thread t)
    {
        ThreadState state = t.ThreadState;
        return state == ThreadState.Running || state == ThreadState.WaitSleepJoin;
    }
    
    请注意,明确指出您应该仅将线程状态用于调试目的,而不用于同步:

    线程状态只对调试场景感兴趣。您的代码不应该使用线程状态来同步线程的活动

    由于您对原子操作感兴趣,我怀疑您是否希望将其用于调试目的(否则您就不必关心它的超精确性)。因此,您可能应该考虑以不同的方式解决实际问题。

    方法
    线程。Join(int毫秒计时)
    可用于安全地测试线程是否已完成。当线程不再处于活动状态时,它返回true

     // 0 == don't wait.
     if (thread.Join(0))
     {
        // remove thread from the list
     }
    

    由于明显的原因,应该从另一个线程调用它。

    这永远不会工作。该线程可能处于其最后一条指令,您的检查将错过最近的保证退出。线程必须与您配合。您需要在更高级别上进行同步。我不知道该怎么做,因为我不知道该应用程序的功能。问一个新问题,详细说明和代码

    请注意,
    t.IsAlive&&t.ThreadState==ThreadState.Running | | t.ThreadState==ThreadState.WaitSleepJoin
    忽略了
    |
    操作符周围的大括号。这并不重要,因为这段代码必须扔掉

    state==ThreadState.WaitSleepJoin
    应该完成什么?这种状态可能是错误的,因为许多库可能会进入这种状态。这一切似乎都是假的

    作为一种解决方法,您可以实现一个看门狗线程:

    while (true)
     DetectExit();
     Sleep(100);
    

    如果线程在检查“goodness”的所有点上都是“good”,则当前函数返回true。我不确定找到一个原子解决方案是否有意义,如果确实存在的话,因为在函数返回true后,线程可能会立即变得不好。假设此代码用于已知线程不会以任何频率从好切换到不好的场景。
    var state=t.ThreadState;返回状态==ThreadState.Running | | state==ThreadState.WaitSleepJoin@Eric J该方法用于删除队列中未运行的线程。如果该方法在队列中留下一个未运行的线程,这是正常的,因为它将在下次该方法运行时被删除。但是试图删除一个仍在运行的线程会导致问题,那么当前的代码就应该可以了。它必须通过所有“良好”检查才能被视为“良好”。如果它没有通过任何一次检查,它将不会运行,也不会自行返回到运行状态。您可能需要考虑依赖于框架提供的工具——即,带有异步/等待的任务可能是合适的。请注意,在将线程分配给本地变量<代码>状态< /代码>之后,线程的真实状态可能会发生改变。方法调用IsThreadGood不是原子的,从指示返回语句处线程的真实状态的意义上讲。然而,根据OP对问题注释中如何使用代码的描述,这并不重要。这并不能解决问题。他已经可以检测到一个已经结束的线程。他已经尽可能可靠地检测到一个线程退出。问题是,线程可以在检查后立即退出。只有在检测到退出时,该检查才有意义。@OP中的usr IsThreadGood()在状态从WaitSleepJoin切换到Running时可能会错误地返回false。我明白了。好的,让我们等待OP的回应,看看他的问题到底是什么。也许这就是他要找的。回答得好。