【问题标题】:Wait for a thread inside a C++ static object等待 C++ 静态对象中的线程
【发布时间】:2020-10-24 04:32:17
【问题描述】:

我有一个需要初始化成像 API 的静态对象。此成像API分配的资源需要由同一个线程释放。
所以我在我的静态对象中启动一个线程来初始化所有东西,然后等待计数器达到零。发生这种情况时,线程会清理所有内容并完成。

这是托管库中的非托管类,因此我不能使用 System::Threading::Thread(需要托管静态成员函数)或 std::thread(编译器错误,/clr 不支持)。

所以我必须像这样开始我的线程:

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Initialize, this, 0, 0);

一切正常,初始化完成,API 函数正常工作。但是当我关闭应用程序时,我看到我的静态对象的使用计数器达到零,但线程从未调用清理函数,就好像线程被杀死一样。有没有办法确保线程将继续存在并执行到结束?

【问题讨论】:

    标签: dll c++14 clr unmanaged managed


    【解决方案1】:

    在以所有可能的方式解决这个问题并添加事件等之后,我想这是不可能的,所以我必须更改我的代码结构并将非托管类封装在托管类中,并将线程添加到托管类。

    【讨论】:

      【解决方案2】:

      我认为您可以通过以下两种方式之一进行:

      • 将资源包装在RAII-style 类中,并进行重构以使对象的生命周期位于您创建的线程的堆栈上,确保在线程循环退出时调用它们的析构函数,而无需调用任何额外的清理。如果当您的计数器达到 0 时线程正确返回没有问题,这应该是解决此问题的最简单和最干净的方法。

      • 我认为您可以使用window procedures 拦截WM_CLOSE 消息,处理必要的清理然后传递消息,有效地“停止”它直到您准备好关闭。请注意,即使您在 DLL 中,您仍然可以设置窗口过程和消息泵系统,您不需要 GUI 来执行此操作。但是,我不能 100% 确定您是否会收到与“拥有”您的 DLL 的应用程序有关的 WM_CLOSE 消息,我还没有尝试过。

      但是,您必须在线程循环中通过events 实现某种形式的消息传递,因为 WindowProc 将在不同的线程上调用,因此您知道何时调用清理过程。

      我对 CLR 也不是很熟悉,因此与这些 API 交互可能比使用原始 C++ 调用和句柄更简单。

      【讨论】:

      • 如果我在减少计数器的对象中放置一个断点,它就会停在那里。如果我在清理函数中设置一个断点,它永远不会停在那里。
      • 好的,一旦计数器达到 0,线程是否正确返回,即使它从未进入清理函数?我从答案中编辑了我的评论,因为显然我可以在这里发表评论^^
      • 我在创建时对其句柄进行了 Debug::Print,在最后的终止线程列表中没有任何痕迹(自动生成的退出线程列表,带有退出代码)
      • 啊,看到你的回答,我想这可能是在托管代码中运行非托管线程的奇怪交互?对不起,我帮不上忙,祝你好运!
      • 是的,实际上使用 CreateThread() 我猜它创建了一个 Win32 线程,应用程序的其余部分没有很好地管理它。我还对另一个托管类和 System::Threading::Thread 进行了一些测试,并且在线程仍然存在时不调用它的终结器(托管析构函数)!这是一种完全不同的行为。
      猜你喜欢
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-07
      相关资源
      最近更新 更多