Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在事件发生时启动线程并正确关闭其句柄_C++_Windows_Multithreading - Fatal编程技术网

C++ 如何在事件发生时启动线程并正确关闭其句柄

C++ 如何在事件发生时启动线程并正确关闭其句柄,c++,windows,multithreading,C++,Windows,Multithreading,我正在创建一个服务,它正在侦听登录事件。如果发生此事件,我的应用程序应该启动一个新线程,该线程将完成工作 我的问题是,如何在每次登录事件发生时启动一个新线程,并在线程正常工作时正确关闭它的句柄。我的问题是,我不知道会发生多少登录事件,所以我不能使用userWaitForMultipleObjects,因为它的第一个参数是它应该等待的线程数 while ( WaitForSingleObject( ghSvcStopEvent, 0 ) != WAIT_OBJECT_0 ) { DWORD d

我正在创建一个服务,它正在侦听登录事件。如果发生此事件,我的应用程序应该启动一个新线程,该线程将完成工作

我的问题是,如何在每次登录事件发生时启动一个新线程,并在线程正常工作时正确关闭它的句柄。我的问题是,我不知道会发生多少登录事件,所以我不能使用user
WaitForMultipleObjects
,因为它的第一个参数是它应该等待的线程数

while ( WaitForSingleObject( ghSvcStopEvent, 0 ) != WAIT_OBJECT_0 )
{
  DWORD dwEventFlags;
  BOOL bRes;

  // WTSWaitSystemEvent waits until a logon event ocurs
  bRes = WTSWaitSystemEvent( WTS_CURRENT_SERVER_HANDLE, WTS_EVENT_LOGON, &dwEventFlags );
  if ( dwEventFlags == WTS_EVENT_NONE )
  {
    ShowErrorText( "Cancelling waiting for logon event. Service shutting down.", 0, true );
  }
  if ( bRes )
  {
    // Someone has logged on
    HANDLE hThread = CreateThread( NULL, 0, ServiceWorkerThread, NULL, 0, &dwThreadID );
  }
  else
  {
    ShowErrorText( "WTSWaitSystemEvent failed.", GetLastError(), true );
  }
}//while
有人能帮我吗

谢谢

如果可以使用C++11(从VS2010开始),可以使用一个条件变量来完成这项工作

条件变量的概念是: 一个允许线程一起通信的变量。 如果您通知它,您将向其上插入的其他线程发送一个信号

如果您对它执行cv.wait(…),那么您将等待其他线程发出信号,表明发生了某个事件,然后再次测试您的条件

这里有一个例子

服务器.h

#include <condition_variable>
#include <mutex>

class CServer
{
    std::condition_variable & cv;
    std::mutex & mut;
    bool & flag;
public:
    ~CServer(void);
    CServer::CServer(std::condition_variable & cv,
                     std::mutex & mut,
                     bool & flag);

    CServer::CServer(CServer &);
    int Notify();
    int DisplayNotification();

    std::condition_variable & getCondVar(){return cv;}
    std::mutex & getMutex(){return mut;}
    bool & getFlag(){return flag;}
};
#包括
#包括
类服务器
{
std::条件变量&cv;
std::mutex&mut;
布尔旗;
公众:
~CServer(void);
CServer::CServer(标准::条件变量和cv,
std::互斥和mut,
布勒和旗帜);
CServer::csserver(csserver&);
int Notify();
int DisplayNotification();
std::condition_变量&getCondVar(){return cv;}
std::mutex&getMutex(){return mut;}
bool&getFlag(){return flag;}
};
Server.cpp

#include "Server.h"
#include <iostream>
using namespace std;





CServer::~CServer(void)
{
}

CServer::CServer(std::condition_variable & cv_,
                 std::mutex & mut_,
                 bool & flag_):
cv(cv_),
mut(mut_),
flag(flag_)
{

}

CServer::CServer(CServer &toCopy):
cv(toCopy.getCondVar()),
mut(toCopy.getMutex()),
flag(toCopy.getFlag())
{
    flag=false;
    cout<<"Copy constructor"<<std::endl;
}

int CServer::Notify()
{
    {
        std::lock_guard<std::mutex> lk(mut);
        flag=true;
        std::cout << "ready for notfication"<<endl;
    }
    cv.notify_one();
    return 0;
}

int CServer::DisplayNotification()
{
    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(mut);
        cv.wait(lk, [this]{return this->getFlag();});
    }
    cout<<"Notification displayed"<<endl;
    return 0;
}
#包括“Server.h”
#包括
使用名称空间std;
CServer::~CServer(无效)
{
}
CServer::CServer(标准::条件变量和cv变量),
标准:互斥和互斥,
bool&flag_):
cv(cv_),
mut(mut_),
旗帜(旗帜)
{
}
CServer::CServer(CServer&toCopy):
cv(toCopy.getCondVar()),
mut(toCopy.getMutex()),
标志(toCopy.getFlag())
{
flag=false;

是否需要等待该线程完成?如果不需要,验证后下一行的
CloseHandle(hThread)
没有返回
NULL
。以某种方式,您需要在验证线程成功启动后立即关闭该句柄,或者在不再需要该句柄后关闭该句柄。(旁注:如果您使用的是C/C++运行库,那么您应该使用,顺便说一句)。我认为您应该使用线程池,而不是在每次登录时创建新线程。@WhozCraig:实际上我不需要等待线程完成。非常感谢。将您的评论作为answear发布,以便我可以接受。@Matt:为什么线程池更好?您知道在哪里可以找到线程池的简单示例吗?@kampi在您的情况下,线程池使用的资源更少。下面是一篇关于Windows线程池API的MSDN文章:
#include <chrono>
#include "Server.h"
class CClient
{
    CServer & serv;
    std::chrono::seconds sleepTime;
    bool finishedWork;
public:
    CClient(CServer & serv, 
            std::chrono::seconds sleepTime);
    ~CClient(void);
    int work();
};
#include "Client.h"
#include <thread>
using namespace std;


CClient::CClient(CServer & serv_,
                 std::chrono::seconds sleepTime_):
serv(serv_),
sleepTime(sleepTime_),
finishedWork(false)
{
}


CClient::~CClient(void)
{
}

int CClient::work()
{
    this_thread::sleep_for(sleepTime);
    finishedWork=true;
    serv.Notify();
    return 0;
}
#include "Client.h"
#include <thread>
using namespace std;

int main()
{
    std::chrono::seconds sleepTime=std::chrono::seconds(10);

    //create client and server
    condition_variable cv;
    mutex mut;
    bool flag=false;

    CServer serv(cv,mut, flag);
    CClient cli(serv,sleepTime);

    //thread with the server
    thread thServ(&CServer::DisplayNotification,serv);

    ////thread with the client
    thread thCli (&CClient::work,cli);

    ////join threads
    thServ.join();
    thCli.join();
    return 0;
}