检测.NET线程是否正在运行

时间:2015-12-29 22:29:40

标签: .net multithreading c++-cli clr

我正在使用C ++ / CLI,我创建了2个主题。

loadedThreads = gcnew array<Thread^>(2);
len = 2;

Thread^ th1 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[0] = th1;
Thread^ th2 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[1] = th2;

th1->Start();
th2->Start();

threadsCreated = true;

两个线程都在检查彼此是否还活着:

void Ping()
{
    while(true)
    {
        if(!threadsCreated) { Thread::Sleep(25); continue; }

        for(int i = 0; i < len; i++)
        {
            Thread^ t = loadedThreads[i];

            if(!t->IsAlive())
            {
                _log("some thread is not running");
            }
        }

        Thread::Sleep(25);
    }
}

但是如果我使用ProcessHacker终止线程,线程将不再运行但仍然会被标记为活动(IsAlive = true,ThreadState = Running)

这是一个错误吗?它是Process Hacker使用的漏洞吗?

1 个答案:

答案 0 :(得分:0)

.NET/CLR threads是托管线程;在应用程序的上下文中管理。托管线程不只是在操作系统中启动一个线程,它们保持线程对象的状态,以便更加开发人员管理线程。

当你启动一个线程时,操作系统必须管理这个线程(无论它来自.NET,Java还是C),而外部程序(如Process Hacker)可以看到这些线程很像外部程序可以看到在系统上运行的进程。 Process Hacker和类似它的可以终止线程的程序通常只是获取操作系统线程ID并调用WinAPI函数TerminateThread,这实际上会杀死活动线程,而不会有任何其他用户代码在其上执行。

对于托管线程,这意味着当您调用Start方法时,Thread类将保持其创建的内部线程的状态(例如线程的ID,将线程状态设置为'running',调用用户函数等)并且当线程函数结束时,Thread类然后清理并设置适当的标志(例如,线程状态设置为'停止'以进行正常终止或'中止'如果{{3} } 被称为)。对此,如果从外部程序(如Process Hacker)中删除线程,Thread类代码没有机会预先形成清理代码,从而将标志重置为其有效值,即,Thread类仍然认为它所拥有的线程是有效的。应该注意的是,在通过Process Hacker杀死它之后对线程对象进行操作很可能会导致崩溃或未定义的行为。

还应该注意的是,没有太多方法可以检测线程是否在代码之外被强行杀死。您可以加入线程或在线程代码中实现一种心跳,但这仍然无法保证(特别是如果您实现任何类型的同步锁)。如果线程被杀死,你可能知道的最多的是线程已经通过某种方式结束,正如你所指出的那样,它可能导致无效状态。

所以,直接回答:

  

这是一个错误吗?

不,这是上下文所预期的行为。

  

它是Process Hacker使用的漏洞吗?

不,根据我上面的回答,它很可能使用TerminateThread函数,但它确实需要管理员权限。

希望可以提供帮助。