Multithreading 在DLL_DETACH中连接线程

Multithreading 在DLL_DETACH中连接线程,multithreading,c++11,winapi,dll,Multithreading,C++11,Winapi,Dll,我有一个被注入进程的DLL,当进程终止时,我希望在DLL卸载时终止线程 因此,我得出以下结论: // Wrapper around std::thread that notifies the task it should stop.. class TaskThread { private: std::mutex mutex; std::thread thread; std::atomic_bool stop; std::function<void()>

我有一个被注入进程的DLL,当进程终止时,我希望在DLL卸载时终止线程

因此,我得出以下结论:

// Wrapper around std::thread that notifies the task it should stop..
class TaskThread {
private:
    std::mutex mutex;
    std::thread thread;
    std::atomic_bool stop;
    std::function<void()> onStop;

public:
    TaskThread(std::function<void(TaskThread*)> &&task, std::function<void()> &&onStop);
    ~TaskThread();

    bool stopped();
};

TaskThread::TaskThread(std::function<void(TaskThread*)> &&task, std::function<void()> &&onStop) : onStop(onStop)
{
    this->thread = std::thread([this, task]{
        task(this);
    });
}

TaskThread::~TaskThread()
{
    //set stop to true..
    std::unique_lock<std::mutex> lock(this->mutex);
    this->stop = true;
    lock.unlock();

    //signal the task
    onStop();

    //join the thread..
    this->thread.join();
}

bool TaskThread::stopped()
{
    std::unique_lock<std::mutex> lock(this->mutex);
    bool stopped = this->stop;
    lock.unlock();
    return stopped;
}



BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    static std::unique_ptr<TaskThread> task_thread;
    static std::unique_ptr<Semaphore> semaphore;

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            DisableThreadLibraryCalls(hinstDLL);

            semaphore.reset(new Semaphore(0));

            task_thread.reset(new TaskThread([&](TaskThread* thread){
                while(thread && !thread->stopped()) {
                    if (!semaphore)
                    {
                        return;
                    }

                    semaphore->wait();
                    if (!thread || thread->stopped())
                    {
                        return;
                    }

                    runTask(); //execute some function
                }
            }, [&]{
                if (semaphore)
                {
                    semaphore->signal();
                }
            }));
        }
            break;

        case DLL_PROCESS_DETACH:
        {
            task_thread.reset(); //delete the thread.. triggering the destructor
        }
            break;
    }
    return TRUE;
}
//std::thread的包装器,通知任务它应该停止。。
类任务线程{
私人:
std::互斥互斥;
标准:螺纹;
标准:原子波停止;
std::函数在顶部;
公众:
TaskThread(std::function&&task,std::function&&onStop);
~taskshread();
布尔停止();
};
TaskThread::TaskThread(std::function&&task,std::function&&onStop):onStop(onStop)
{
this->thread=std::thread([this,task]{
任务(本);
});
}
TaskThread::~TaskThread()
{
//将stop设置为true。。
std::unique_lock锁(此->互斥锁);
此->停止=真;
lock.unlock();
//发出任务信号
顶部();
//加入线程。。
这个->线程.join();
}
bool TaskThread::stopped()
{
std::unique_lock锁(此->互斥锁);
bool stopped=此->停止;
lock.unlock();
返回停止;
}
BOOL APIENTY DllMain(HINSTANCE hinstDLL、DWORD FDFREASON、LPVOID lpvReserved)
{
静态std::唯一的任务线程;
静态std::唯一的ptr信号量;
开关(FDSON)
{
案例DLL\u进程\u附加:
{
禁用线程库调用(hinstDLL);
信号量重置(新信号量(0));
task_thread.reset(新任务线程([&](任务线程*线程){
while(thread&!thread->stopped()){
if(!信号量)
{
回来
}
信号量->等待();
如果(!thread | | thread->stopped())
{
回来
}
runTask();//执行一些函数
}
}, [&]{
if(信号量)
{
信号量->信号();
}
}));
}
打破
案例DLL\u进程\u分离:
{
task_thread.reset();//删除线程..触发析构函数
}
打破
}
返回TRUE;
}
但是,这将导致退出时程序挂起。。我必须通过任务管理器来杀死它。如果我拆下线程,一切都会正常工作并干净地退出(不管是在创建线程之后还是在析构函数中拆下线程)


那么,为什么在我加入线程时进程会挂起呢?

调用
DllMain()
时会持有一个锁,因此等待线程退出最终是对
DllMain()
的递归调用(
thread\u DETACH
process\u DETACH
)并挂起该锁


进一步阅读:

调用
DllMain()
时会持有一个锁,因此等待线程退出最终是对
DllMain()
thread\u DETACH
PROCESS\u DETACH
)的递归调用,并挂起该锁


进一步阅读:

有许多关于在
DllMain()中做事的危险的文章。
谢谢!那我得多读些。似乎在上面的代码中获取互斥体也会导致死锁。。我必须找到另一种方法或遵循最佳实践,并在
DLL\u THREAD\u DETACH
中发出事件信号。。有很多关于在
DllMain()中做事的危险性的文章。
谢谢!那我得多读些。似乎在上面的代码中获取互斥体也会导致死锁。。我必须找到另一种方法或遵循最佳实践,并在
DLL\u THREAD\u DETACH
中发出事件信号。。