出于某种原因,我需要在 .dll 中有一个全局对象,它管理一个 std::thread
。它是通过以下方式实现的:
#include "Header.h"
#include <thread>
#include <condition_variable>
#include <mutex>
class Foo
{
public:
Foo () : m_closeThread (false)
{
m_thread = std::thread (&Foo::ThreadProc, this);
}
~Foo ()
{
{
std::unique_lock<std::mutex> lock (m_mutex);
m_closeThread = true;
}
m_cv.notify_one ();
m_thread.join ();
}
private:
void ThreadProc ()
{
while (true)
{
std::unique_lock<std::mutex> lock (m_mutex);
m_cv.wait (lock, [this] () { return m_closeThread; });
if (m_closeThread)
break;
}
}
private:
bool m_closeThread;
std::thread m_thread;
std::condition_variable m_cv;
std::mutex m_mutex;
};
Foo& GetFoo ()
{
static Foo foo;
return foo;
}
extern "C" void Function ()
{
auto& foo = GetFoo ();
}
但是,当应用程序关闭时,在 ~Foo
执行之前,.dll 的所有工作线程都会被杀死,或者作为输出窗口MSVS2015 说:
The thread 0x1040 has exited with code 0 (0x0).
并且,由于这个事实(Source0,Source1),如果使用 Windows 7(在 Windows 上不阻塞),应用程序会阻塞 m_cv.notify_one ();
调用8 及以上)。
事实上,它在一个特定版本的 Windows 上阻塞,而不在其他版本上阻塞,这让我认为,某种 UB 是罪魁祸首(例如 DLL 卸载排序相关问题,因为如果这样的话,这样的问题是不可重现的对象不在 .dll 中),但我想不出解决方案,它允许我优雅地关闭线程,同时让对象成为全局对象(因为,需要进行主要的应用程序重组,使其不是全局的)。
那么,能否在线程被 Windows 平台杀死之前优雅地关闭线程?
旁注 0:
为了示例的完整性,
这是 DLLMain:
#include <Windows.h>
BOOL APIENTRY DllMain (HMODULE, DWORD, LPVOID) { return TRUE; }
这是 .dll 的 header :
#pragma once
extern "C" void Function ();
这是控制台应用程序,使用上述 .dll:
#include "..\Test\Header.h"
#include <chrono>
#include <thread>
int main ()
{
Function ();
using namespace std::chrono_literals;
std::this_thread::sleep_for (2s);
}
旁注 1:
我目前最多只能使用 C++11(或者 MSVS 2015 中存在的任何功能)。
最佳答案
当 WinMain
返回时,运行时调用 ExitProcess
.要做的第一件事是“1. 进程中的所有线程,除了调用线程,在没有收到 DLL_THREAD_DETACH
通知的情况下终止它们的执行。”
关于c++ - 在 DLL 中运行的工作线程在应用程序关闭时被杀死,然后才能正常关闭它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54444387/