认识Windows系统线程池可以参考这篇:
https://baike.baidu.com/item/%E7%BA%BF%E7%A8%8B%E6%B1%A0/4745661
需要强调的是下面这句:
调用QueueUserWorkItem时传入的Object类型参数传递到任务过程,可以通过这种方式来向任务过程传递参数:
如果任务过程需要多个参数,可以定义包含这些数据的类,并将其强制转换为Object数据类型
在MS提供的Windows Service的C++例程中,提供了一个类,就是使用这种方式(定义一个工作者类)来传递多个线程参数
这个类的定义如下:
class CThreadPool
{
public:
template
static void QueueUserWorkItem(void (T::*function)(void), T *object, ULONG flags = WT_EXECUTELONGFUNCTION/*告诉操作系统工作项目需要长时间的工作*/)
{
//std::pair主要的作用是将两个数据组合成一个数据,两个数据可以是同一类型或者不同类型。
//std::pair实质上是一个结构体,其主要的两个成员变量是first和second,这两个变量可以直接作为成员变量来使用
typedef std::pair
std::auto_ptr
/******************************************************************************************************************
WT_EXECUTEDEFAULT :工作项目放入非I/O组件得线程中。
WT_EXECUTEINIOTHREAD :工作项目放入I/O组件的线程中,这样的线程在I/O请求没有完成之前不会被终止运行,防止因为线程被终止导致I/O请求丢失。
WT_EXECUTEINPERSISTENTTHREAD :放入永久线程池。
WT_EXECUTELONGFUNCTION :工作项目需要长时间的工作,系统会据此安排更多的线程。
*************************************************************************************************************************/
if (::QueueUserWorkItem(ThreadProc
{
//这样智能指针析构函数就不会delete 掉"new CallbackType(function, object)"分配的指针了, 工作线程会完成这个释放。
p.release();
}
else
{
throw GetLastError();
}
}
private:
template
static DWORD WINAPI ThreadProc(PVOID context)
{
typedef std::pair
//auto_ptr析构的时候肯定会删除他所拥有的那个对象,所以我们就要注意了,一个萝卜一个坑,两个auto_ptr不能同时拥有同一个对象。像这样:
// int*p = new int(0);
// auto_ptr
// auto_ptr
// 因为ap1与ap2都认为指针p是归它管的,在析构时都试图删除p, 两次删除同一个对象的行为在C++标准中是未定义的。所以我们必须防止这样使用auto_ptr.
//======================
//int*pa = new int[10];
//auto_ptr
//因为auto_ptr的析构函数中删除指针用的是delete, 而不是delete[], 所以我们不应该用auto_ptr来管理一个数组指针。
std::auto_ptr
(p->second->*p->first)();
return 0;
}
};
////// 定义一个工作类,用来帮助进行工作线程参数传递
class CTCPRequsetJob
{
SOCKET m_socket;
HWND m_hWndProcessMsg;
public:
HWND m_hWndCmdSource;
char m_rxbuf[4096];
int m_rxdataLen;
enum { enum_select_error, enum_select_outof_time, enum_server_is_closed, enum_recv_success };
void ServiceWorkerThread(void);
CTCPRequsetJob(SOCKET socket, HWND hWndCmdSource, HWND hWndProcessMsg);
~CTCPRequsetJob();
};
CTCPRequsetJob::CTCPRequsetJob(SOCKET socket, HWND hWndCmdSource, HWND hWndProcessMsg) :
m_socket(socket), m_hWndCmdSource(hWndCmdSource), m_hWndProcessMsg(hWndProcessMsg)
{
m_rxdataLen = 0;
}
CTCPRequsetJob::~CTCPRequsetJob()
{
}
void CTCPRequsetJob::ServiceWorkerThread(void)
{
//使用select方法监控tcp客户端的接入
int ret = 0;
timeval tTimeout;
fd_set sReadSet;
// Perform main service function here...
tTimeout.tv_sec = 2;
tTimeout.tv_usec = 0;
FD_ZERO(&sReadSet);
FD_SET(m_socket, &sReadSet);
ret = select(1, &sReadSet, NULL, NULL, &tTimeout);
if (ret < 0){
PostMessage(m_hWndProcessMsg, WM_SOCKET_RESPONSE, (WPARAM)enum_select_error, (LPARAM)this);
}
//
else if (0 == ret){
PostMessage(m_hWndProcessMsg, WM_SOCKET_RESPONSE, (WPARAM)enum_select_outof_time, (LPARAM)this);
}
//
else{
ret = recv(m_socket, m_rxbuf, sizeof(m_rxbuf), 0);
if (ret <= 0){
PostMessage(m_hWndProcessMsg, WM_SOCKET_RESPONSE, (WPARAM)enum_server_is_closed, (LPARAM)this);
}
else{
PostMessage(m_hWndProcessMsg, WM_SOCKET_RESPONSE, (WPARAM)enum_recv_success, (LPARAM)this);
m_rxdataLen = ret;
}
}
//线程结束,销毁这个工作者对象
delete this;
}
///----工作者线程的创建
//创建一个工作线程来接收服务端的相应,构造函数入口参数将传递给工作者线程使用
CTCPRequsetJob* job = new CTCPRequsetJob(m_socket, hWndRequestSource, GetSafeHwnd());
CThreadPool::QueueUserWorkItem(&CTCPRequsetJob::ServiceWorkerThread, job);