出于某种原因,我需要在管理std::thread
的.dll中有一个全局对象。它是通过以下方式实现的:
#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的输出窗口所述:
线程0x1040已退出,代码为0(0x0)。
并且由于这一事实(Source0,Source1),如果使用Windows 7,则该应用程序会在m_cv.notify_one ();
调用时阻塞(在Windows 8及更高版本上不会阻塞)
事实上,它阻止在一个特定版本的Windows上,而不是在其他特定版本的Windows上,使我认为,应该归咎于某种类型的UB(例如与DLL卸载顺序相关的问题,因为如果这样的问题不能重现,对象不在.dll中),但是我没有想到解决方案,该解决方案使我可以优雅地关闭线程,同时使对象成为全局对象(因为,需要进行主要的应用程序重组,以使其变为非全局对象)。
那么,在Windows平台杀死线程之前,可以优雅地关闭线程吗?
注释0:
为了示例完整性,
这是DLLMain:
#include <Windows.h>
BOOL APIENTRY DllMain (HMODULE, DWORD, LPVOID) { return TRUE; }
这是.dll的标题:
#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中提供的任何功能)。
答案 0 :(得分:1)
当$('#table1, table2, table3').dataTable({
initComplete: function() {
var column = this.api().column(0);
var $targetFilter = $(this).prev('.selectTriggerFilter');
var select = $('<select class="filter"><option value=""></option></select>')
.appendTo($targetFilter)
.on('change', function() {
var val = $(this).val();
column.search(val).draw()
});
}
});
返回时,运行时将调用ExitProcess
。要做的第一件事是“ 1.进程中的所有线程(调用线程除外)都终止其执行,而没有收到WinMain
通知。”