简单的 Worker 线程类






3.07/5 (15投票s)
一个简单的 Worker 线程类,支持 Join 和线程消息发布
引言
很多时候我们需要创建工作线程,通常我们希望在主线程中等待所有工作线程完成执行,类似于pthread
的pthread_join
调用。我们希望在工作线程完成时收到通知;检查工作线程的状态,例如它是否仍在线程函数中执行或者已经完成等。有时我们甚至希望在线程函数完成后保持工作线程的存活,以便我们可以重新提交不同的任务(通常在线程池中)。所有这些都可以通过管理事件对象的状态来完成,例如发出信号或未发出信号等。使用不同的事件对象来管理这样的代码是很困难的。我将所有这些常用的工作线程功能整合到了WorkerThread
类的基本实现中。
WorkerThread 类
WorkerThread
是工作线程的基本实现,具有PostThreadMessage
、Join
、RegisterOnCompleteRoutine
和线程执行状态。它可以进一步增强以实现更多其他功能,但我想保持想法的简单性。在这里,我的主要重点是展示如何使用PostThreadMessage
来处理工作线程。
Using the Code
在您现有的应用程序中使用WorkerThread
类非常简单。您只需要将 *WorkerThread.cpp* 添加到您的项目中,并在您想使用该类的地方包含 *WorkerThread.h*。
在您想要创建工作线程的任何地方添加WorkerThread
类的变量。使用Start()
创建一个工作线程,可以包含一个可选的自动退出参数(默认为true
),要结束线程,请使用End()
方法。如果自动退出参数为true
,则无需调用WorkerThread
类的End()
方法。Join()
方法会简单地使调用线程等待直到工作线程完成其执行。GetStatus()
会告诉你当前的线程状态(NotCreated
、Created
、Started
、Restarted
、Complete
)。ReExecute()
方法只能用于非自动退出线程(在构造函数中使用false
参数创建),可以使用不同或相同的数据(这可以进一步增强以避免覆盖数据)。RegisterOnCompleteRoutine()
方法可用于注册一个可选的例程,该例程将在线程函数完成后被调用。
以下是展示WorkerThread
类用法的示例代码
#include "stdafx.h"
#include "WorkerThread.h"
#define MAXCOUNT 5
DWORD WINAPI ThreadProc(void *param)
{
int i = (int)param;
//
// your code
//
return 0;
}
DWORD WINAPI OnComplete(void *param)
{
int i = (int)param;
printf("OnComplete data = %d\n", i);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
// Create few worker threads with autoQuit false
WorkerThread workerThread[MAXCOUNT] = {false, false, false, false, false};
// Register an optional completion routine
workerThread[2].RegisterOnCompleteRoutine(OnComplete, (void *)1234);
// Start all of them
for (int i = 0; i < MAXCOUNT; ++i) {
if (workerThread[i].Start(ThreadProc, (void *)i)) {
printf("Started %d\n", i);
}
}
for (int i = 0; i < MAXCOUNT; ++i) {
if (workerThread[i].ReExecute((void *)i)) {
printf("Restarted %d\n", i);
}
}
for (int i = 0; i < MAXCOUNT; ++i) {
workerThread[i].End();
}
// main thread will wait here, till all others finish.
for (int i = 0; i < MAXCOUNT; ++i) {
workerThread[i].Join();
}
return 0;
}
关注点
请注意在ThreadProc()
开始时的虚拟PeekMessage()
调用,只是为了强制为我们的工作线程创建一个消息队列。
历史
- 2009年5月5日:初始版本