如何将类非静态成员方法传入CreateThreadPoolWork函数?
解决CreateThreadPoolWork调用类非静态成员函数的问题
直接将类非静态成员函数强转为PTP_WORK_CALLBACK是错误的——非静态成员函数隐含一个this指针参数,其函数签名和PTP_WORK_CALLBACK不匹配,强转后会导致调用时参数混乱,程序无法正常运行。静态成员函数虽能匹配签名,但无法访问类的非静态成员属性。
以下是两种简便的解决方案:
方案1:静态包装函数 + 实例指针作为上下文
利用CreateThreadPoolWork的第二个参数pvContext传递类实例的this指针,编写静态包装函数适配回调签名,在包装函数中转回实例指针并调用目标成员函数:
#include <windows.h> #include <iostream> class A{ public: void print() { std::cout << "Hello from instance! Member value: " << m_member << std::endl; } // 静态包装函数,严格匹配PTP_WORK_CALLBACK签名 static void CALLBACK WorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work) { // 将上下文指针转为A类实例指针 A* instance = static_cast<A*>(Context); // 调用目标成员函数 instance->print(); // 无需复用Work对象时可在此关闭(也可在外部合适时机处理) CloseThreadPoolWork(Work); } void ctpw() { TP_ENVIRONMENT tpenv; InitializeThreadpoolEnvironment(&tpenv); // 传递this作为上下文,传入静态包装函数 PTP_WORK pw = CreateThreadPoolWork(&A::WorkCallback, this, &tpenv); if (pw != nullptr) { // 提交线程池任务 SubmitThreadPoolWork(pw); } // 示例:等待任务执行完成(实际需根据业务逻辑处理同步) Sleep(100); DestroyThreadpoolEnvironment(&tpenv); } private: int m_member = 123; // 类成员属性,可在print中直接访问 };
方案2:无捕获Lambda适配器(C++11及以上)
利用无捕获Lambda可转换为普通函数指针的特性,省去单独编写静态成员函数的步骤,写法更简洁:
#include <windows.h> #include <iostream> class A{ public: void print() { std::cout << "Hello from instance! Member value: " << m_member << std::endl; } void ctpw() { TP_ENVIRONMENT tpenv; InitializeThreadpoolEnvironment(&tpenv); // 无捕获Lambda,适配PTP_WORK_CALLBACK签名 auto workCallback = [](PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work) { static_cast<A*>(Context)->print(); CloseThreadPoolWork(Work); }; // 将Lambda转换为PTP_WORK_CALLBACK,传递this作为上下文 PTP_WORK pw = CreateThreadPoolWork( reinterpret_cast<PTP_WORK_CALLBACK>(workCallback), this, &tpenv ); if (pw != nullptr) { SubmitThreadPoolWork(pw); } Sleep(100); DestroyThreadpoolEnvironment(&tpenv); } private: int m_member = 123; };
注意事项
- 确保线程执行任务时,类实例
A*处于有效状态,不能提前销毁,否则会触发未定义行为。 - 线程池对象(如
PTP_WORK)使用完毕后需调用CloseThreadPoolWork释放资源。 TP_ENVIRONMENT需正确初始化和销毁,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Jahnoh44
相关产品推荐
相关产品推荐

