如何复用CWinThread?两类相关技术问题咨询
CWinThread复用相关问题解答
以下是你提供的原始示例代码:
class MyClass { friend UINT ThreadFunc(void* parameter); public: MyClass() { m_thread = AfxBeginThread(ThreadFunc, this, 0, 0, CREATE_SUSPENDED); m_thread->m_bAutoDelete = false; } ~MyClass() { delete m_thread; } int Value() const { return m_value; } void Calculate(int value) { m_value = value; m_thread->ResumeThread(); } private: CWinThread* m_thread = nullptr; int m_value = 0; }; inline UINT ThreadFunc(void* parameter) { auto* mc = reinterpret_cast<MyClass*>(parameter); mc->m_value *= 2; return 0; }
问题
- 能否重写Calculate方法,使其支持连续调用(当前类仅能完成首次计算),实现如下调用逻辑:
MyClass mc; mc.Calculate(1); // Waiting for mc to finish... std::cout << mc.Value() << std::endl; mc.Calculate(2); // Waiting for mc to finish... std::cout << mc.Value() << std::endl;
猜测可通过创建任务队列,让线程循环检查队列直至停止来实现。
- 是否可以在线程创建完成后修改其控制函数?
解答
问题1:支持连续调用的实现方式
你的猜测完全正确,核心是让线程进入循环等待任务的状态,而非执行一次就退出。需要结合任务队列和同步机制实现线程复用,具体修改如下:
- 添加同步对象与任务队列,用于存储待处理的计算任务;
- 修改线程函数,使其循环等待任务通知,处理完成后反馈主线程;
- 重写
Calculate方法,将任务加入队列并唤醒线程,同时支持等待任务完成。
修改后的示例代码(补充同步机制,省略部分边界检查):
#include <queue> #include <afxmt.h> // MFC同步类头文件 class MyClass { friend UINT ThreadFunc(void* parameter); public: MyClass() : m_hTaskEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)), m_hFinishEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)) { m_thread = AfxBeginThread(ThreadFunc, this, 0, 0, CREATE_SUSPENDED); m_thread->m_bAutoDelete = false; m_thread->ResumeThread(); // 启动线程进入等待状态 } ~MyClass() { // 发送停止信号,等待线程安全退出 m_bStop = true; SetEvent(m_hTaskEvent); WaitForSingleObject(m_thread->m_hThread, INFINITE); CloseHandle(m_hTaskEvent); CloseHandle(m_hFinishEvent); delete m_thread; } int Value() const { CCriticalSectionLock lock(m_cs); return m_value; } void Calculate(int value) { { CCriticalSectionLock lock(m_cs); m_taskQueue.push(value); } SetEvent(m_hTaskEvent); // 唤醒线程处理任务 WaitForSingleObject(m_hFinishEvent, INFINITE); // 等待任务完成 } private: CWinThread* m_thread = nullptr; int m_value = 0; std::queue<int> m_taskQueue; CCriticalSection m_cs; // 保护队列和共享数据,避免多线程竞争 HANDLE m_hTaskEvent; // 通知线程有新任务 HANDLE m_hFinishEvent; // 通知主线程任务完成 bool m_bStop = false; // 线程停止标志 }; inline UINT ThreadFunc(void* parameter) { auto* mc = reinterpret_cast<MyClass*>(parameter); while (!mc->m_bStop) { // 等待任务通知 WaitForSingleObject(mc->m_hTaskEvent, INFINITE); if (mc->m_bStop) break; int taskValue = 0; { CCriticalSectionLock lock(mc->m_cs); if (!mc->m_taskQueue.empty()) { taskValue = mc->m_taskQueue.front(); mc->m_taskQueue.pop(); } } // 执行计算逻辑 { CCriticalSectionLock lock(mc->m_cs); mc->m_value = taskValue * 2; } SetEvent(mc->m_hFinishEvent); // 通知主线程任务完成 } return 0; }
关键说明:
- 线程启动后进入循环,通过
WaitForSingleObject阻塞等待任务事件; Calculate方法将任务加入队列并触发事件,同时等待完成事件后返回;- 用临界区
CCriticalSection保护共享资源,避免多线程数据竞争; - 析构函数中发送停止信号,确保线程安全退出。
问题2:能否修改已创建线程的控制函数
不可以。CWinThread创建后,线程的入口函数(即你传入的ThreadFunc)由系统内核绑定,一旦线程启动,无法动态修改其入口控制函数。
如果需要让线程执行不同逻辑,可通过以下间接方式实现:
- 将任务封装为可调用对象(如函数指针、
std::function),存入任务队列,线程取出后执行对应逻辑; - 在原线程函数中添加分支判断,根据不同任务类型执行不同处理代码;
- 定义抽象任务基类,派生不同任务子类,线程执行多态的任务接口。
这些方式都是在原线程入口函数框架内动态切换逻辑,而非修改线程本身的控制函数。
内容的提问来源于stack exchange,提问作者qloq
相关产品推荐
相关产品推荐

