如何确保在终结器完成之前终止线程

时间:2015-09-16 06:25:14

标签: multithreading garbage-collection c++-cli finalizer

我有一个非托管类正在运行子Win32窗口的消息循环。当程序关闭时,它会启动托管类的终结器,该类保存对此类的非托管引用。因为另一个线程依赖于这个类,我需要终结器等待消息循环线程完成一个循环并退出并终止。但是,对于GC终结器线程,我显然需要很长的超时循环,否则主线程终止会破坏整个进程。

有没有办法告诉GC没有超时终结器的线程? I.E. - 我需要终结器线程在终结器中阻塞一段时间,这样它就可以完成终止消息循环线程,然后释放非托管资源。

这是我的终结者,因此您可以了解正在发生的事情:

PONms::NestedWin32::
!NestedWin32()
{

    if (msgLoop->IsAlive)
    {
        winProcess->EndThread(); // blocks and waits for message loop thread to terminate
                                // and GC apparently doesn't like this causeing the
                                // entire process to terminate here.
    }
    if (childHandle != nullptr)
    {
        DestroyWindowCore(childHandle);
    }
    if (winProcess != nullptr)
    {
        delete winProcess; // memory leak due to resource not being released
    }
}

我认为我以错误的方式解决了这个问题,只是希望代码能够正常运行并完成终结器。

这是我用来轮询其他线程以查看它是否已终止的简单方法:

void PONms::NestedWin32UM::
EndThread()
{
    int timeOut = 5000;
    threadContinue = false;
    SendNotifyMessage(childWin, WM_CLOSE, 0, 0);
    while (threadActive && timeOut > 0)
    {
        POCPP::Threading::SleepThreadOne();
        timeOut--;
    }
}

1 个答案:

答案 0 :(得分:2)

int timeOut = 5000;

这与终结器线程超时的默认CLR策略非常不匹配。你有2秒的时间完成工作。现代处理器上大约有100亿条指令。我们看不到SleepThreadOne()的作用,但Sleep(1)不会睡眠1毫秒。默认睡眠粒度为15.625毫秒,所以你最终会等待78秒。

从技术上讲,您可以通过自定义托管CLR,ICLRPolicyManager::SetTimeout() method,OPR_FinalizerRun设置来延长超时。但是,实际上,如果你不能用100亿条指令来破解它,那么扩展它就不太可能带来缓解。

调试这并不是那么简单,那些2秒匆忙结束。看结构修复。不要使用 bool 来同步代码,使用事件(CreateEvent winapi函数)。和WaitForSingleObject()一起超时等待它被设置。最大使用1000毫秒,这样你就可以为终结器线程提供足够的呼吸空间。并且不要太好,要求消息循环退出,WM_CLOSE太友好了。代码很容易通过“保存更改”来响应它?消息框,这是一个保证失败。使用PostQuitMessage()。或者根本不打扰,程序应该通过UI终止,你似乎需要以另一种方式拉动地毯。