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