使用私有成员函数调用 Win32 QueueUserWorkItem()
Posted
技术标签:
【中文标题】使用私有成员函数调用 Win32 QueueUserWorkItem()【英文标题】:Calling Win32 QueueUserWorkItem() with a private member function 【发布时间】:2016-08-06 16:45:13 【问题描述】:我正在尝试使用 Win32 函数 QueueUserWorkItem()
将私有成员函数(不应作为公共或受保护的)调用为工作项。我知道我以前做过,而且很容易,但现在我找不到那个 sn-p,也不能让 bind()
voodoo 工作。因此,就这个问题而言,该类是:
class Arbitrary
public:
Arbitrary() ;
~Arbitrary() ;
bool UsefulPublicFunction(unsigned uParameter) ;
protected:
private:
void PrivateWorkItem(void* pVoid) ;
;
在UsefulPublicFunction()
内部,我们可能会看到:
LPTHREAD_START_ROUTINE pThreadStartRoutine ;
ULONG uFlags = 0 ;
void* pContext = nullptr ;
if (QueueUserWorkItem(pThreadStartRoutine, pContext, uFlags))
//blah blah blah
我似乎在杂草丛生的地方是分配给pThreadStartRoutine
,例如:
pThreadStartRoutine = std::bind<&Arbitrary::PrivateWorkItem, this, std::placeholders::_1> ;
我知道PrivateWorkItem
的签名可能应该更改为:
private:
DWORD WINAPI PrivateWorkItem(void* pVoid) ;
即使有了这样的改变,也没有喜悦。 VS2015 真的很讨厌我使用bind()
的方式。
我对@987654331@ 的分配应该是什么样的?
【问题讨论】:
了解您看到的错误会很有帮助。 请求了错误消息......对我来说它没用 - 也许对你来说很有意义:“没有重载函数的实例“std::bind”与所需的类型匹配” 【参考方案1】:这似乎有效:
#include <Windows.h>
#include <stdio.h>
#include <functional>
using namespace std::placeholders;
class Arbitrary
public:
bool UsefulPublicFunction(int uParameter);
protected:
private:
typedef std::function<void (void)> CallbackType;
static DWORD WINAPI ProcessWorkItem(void* pVoid);
void PrivateWorkItem1(int arg1, int arg2);
void PrivateWorkItem2(char * arg1);
;
void Arbitrary::PrivateWorkItem1(int arg1, int arg2)
printf("Numbers are %u %u\n", arg1, arg2);
return;
void Arbitrary::PrivateWorkItem2(char * arg1)
printf("String is %s\n", arg1);
return;
DWORD WINAPI Arbitrary::ProcessWorkItem(void* pVoid)
CallbackType * callback = static_cast<CallbackType *>(pVoid);
(*callback)();
delete callback;
return 0;
bool Arbitrary::UsefulPublicFunction(int param1)
QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem1, this, param1, 7)), 0);
QueueUserWorkItem(&ProcessWorkItem, new CallbackType(std::bind(&Arbitrary::PrivateWorkItem2, this, (char *)"This is my string")), 0);
Sleep(1000);
return true;
int main(int argc, char ** argv)
Arbitrary x;
x.UsefulPublicFunction(5);
return 0;
【讨论】:
对不起,我还没有足够的分数来提高“分数”哈利。【参考方案2】:试试类似的方法:
class Arbitrary
public:
Arbitrary() ;
~Arbitrary() ;
bool UsefulPublicFunction(unsigned uParameter);
protected:
private:
static DWORD WINAPI PrivateWorkItem(void* pVoid) ;
void PrivateFunction();
;
DWORD WINAPI Arbitrary::PrivateWorkItem(void* pVoid)
static_cast<Arbitrary*>(pVoid)->PrivateFunction();
return 0;
...
if (QueueUserWorkItem(&PrivateWorkItem, this, 0))
//blah blah blah
【讨论】:
“感觉”相当笨重,对我来说,从长期代码维护的角度来看似乎并不可靠——主要是因为类中实际上有许多独特的私有工作者函数。但是,是的,我已经按照您建议的方式完成了它,并且我还使用正确的签名声明了自动变量,然后使用 memcpy 将其猛烈撞击到 pThreadStartRoutine 中,但这对我来说似乎同样笨拙。就这一点而言,当实习生在 10 年内维护此代码时,使用 bind 似乎很简单。 您不能真正使用std::bind()
来设置Win32 API 回调函数(请参阅***.com/questions/18161680)。我上面展示的是不涉及丑陋黑客的“最干净”的解决方案。
您大概可以使用一个静态函数,该函数接受指向由 std::bind 生成的转发调用包装器的指针。只要对包装器的调用来自 C++ 而不是 Windows。
感谢 Remy 和 Harry 的快速回复。
回到最初的问题,我想澄清一下。 PrivateWorkItem (pVoid) 的参数已经被提及,因此我们不能将其重新用于其他用途,例如类指针。我对这个问题思考得越多,它看起来就越复杂,所以我确信我遗漏了一些明显的东西。想象一下 Arbitrary 类有 30 个私有工作项 - 你将如何解决这个问题?以上是关于使用私有成员函数调用 Win32 QueueUserWorkItem()的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 gmock 模拟修改 C++ 类中的私有变量的成员函数?