用MFC写一个线程池demo
时间: 2023-11-14 10:25:07 浏览: 37
以下是一个简单的基于 MFC 的线程池 demo。该线程池使用一个任务队列来存储待执行的任务,当有空闲线程时,线程池从队列中取出任务并分配给空闲线程执行。
首先我们需要定义一个任务类,用于存储待执行的任务:
```cpp
class CTask
{
public:
virtual ~CTask() {}
virtual void Run() = 0;
};
```
接下来定义线程池类:
```cpp
class CThreadPool
{
public:
CThreadPool(int nMaxThreads = 5);
~CThreadPool();
void AddTask(CTask* pTask);
private:
static UINT __stdcall ThreadProc(LPVOID lpParam);
void WaitForAllWorkers();
CTask* GetTaskFromQueue();
int m_nMaxThreads;
CArray<HANDLE, HANDLE> m_arrWorkerThreads;
CList<CTask*> m_TaskQueue;
CCriticalSection m_csTaskQueue;
CEvent m_eventNoMoreTasks;
bool m_bStop;
};
```
构造函数 `CThreadPool(int nMaxThreads = 5)` 用于初始化线程池并创建指定数量的工作线程。`AddTask(CTask* pTask)` 用于向任务队列中添加任务。`ThreadProc(LPVOID lpParam)` 是工作线程的入口函数,用于从任务队列中取出任务并执行。`WaitForAllWorkers()` 用于等待所有工作线程退出。`GetTaskFromQueue()` 用于从任务队列中获取一个任务。
接下来我们实现这些函数:
```cpp
CThreadPool::CThreadPool(int nMaxThreads)
: m_nMaxThreads(nMaxThreads)
, m_bStop(false)
{
for (int i = 0; i < m_nMaxThreads; ++i)
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, this, 0, NULL);
if (hThread)
{
m_arrWorkerThreads.Add(hThread);
}
}
}
CThreadPool::~CThreadPool()
{
m_bStop = true;
WaitForAllWorkers();
}
void CThreadPool::AddTask(CTask* pTask)
{
CAutoLock lock(m_csTaskQueue);
m_TaskQueue.AddTail(pTask);
m_eventNoMoreTasks.ResetEvent();
}
UINT __stdcall CThreadPool::ThreadProc(LPVOID lpParam)
{
CThreadPool* pPool = (CThreadPool*)lpParam;
while (!pPool->m_bStop)
{
CTask* pTask = pPool->GetTaskFromQueue();
if (pTask)
{
pTask->Run();
delete pTask;
}
}
return 0;
}
void CThreadPool::WaitForAllWorkers()
{
WaitForMultipleObjects(m_arrWorkerThreads.GetSize(), m_arrWorkerThreads.GetData(), TRUE, INFINITE);
m_arrWorkerThreads.RemoveAll();
}
CTask* CThreadPool::GetTaskFromQueue()
{
CAutoLock lock(m_csTaskQueue);
if (m_TaskQueue.IsEmpty())
{
m_eventNoMoreTasks.SetEvent();
return NULL;
}
CTask* pTask = m_TaskQueue.RemoveHead();
return pTask;
}
```
在构造函数中,我们创建指定数量的工作线程,并将线程句柄存储在 `m_arrWorkerThreads` 中。在析构函数中,我们设置 `m_bStop` 为 true,然后等待所有工作线程退出。
在 `AddTask(CTask* pTask)` 中,我们使用 `CAutoLock` 对任务队列进行加锁,然后将任务添加到队列尾部。如果任务队列之前为空,则需要重置事件 `m_eventNoMoreTasks`。
`ThreadProc(LPVOID lpParam)` 是工作线程的入口函数,它首先调用 `GetTaskFromQueue()` 从任务队列中获取一个任务。如果获取到了任务,则执行它,并释放资源。
在 `WaitForAllWorkers()` 中,我们使用 `WaitForMultipleObjects` 等待所有工作线程退出。
在 `GetTaskFromQueue()` 中,我们使用 `CAutoLock` 对任务队列进行加锁,然后从队列头部获取一个任务。如果任务队列为空,则设置事件 `m_eventNoMoreTasks` 并返回 NULL。
最后,我们需要定义一个任务类的具体实现:
```cpp
class CMyTask : public CTask
{
public:
virtual void Run()
{
// 执行具体的任务
}
};
```
使用该线程池时,首先需要创建一个线程池对象:
```cpp
CThreadPool threadPool(5);
```
然后,我们可以创建一些任务并将它们添加到线程池中:
```cpp
CMyTask* pTask1 = new CMyTask();
CMyTask* pTask2 = new CMyTask();
threadPool.AddTask(pTask1);
threadPool.AddTask(pTask2);
```
最后,我们需要等待所有任务执行完毕:
```cpp
threadPool.WaitForNoMoreTasks();
```
完整代码如下: