You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复用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;
}

问题

  1. 能否重写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. 是否可以在线程创建完成后修改其控制函数?

解答

问题1:支持连续调用的实现方式

你的猜测完全正确,核心是让线程进入循环等待任务的状态,而非执行一次就退出。需要结合任务队列和同步机制实现线程复用,具体修改如下:

  1. 添加同步对象与任务队列,用于存储待处理的计算任务;
  2. 修改线程函数,使其循环等待任务通知,处理完成后反馈主线程;
  3. 重写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:37:36