线程调用成员函数
Posted
技术标签:
【中文标题】线程调用成员函数【英文标题】:Thread call member function 【发布时间】:2013-10-05 18:50:58 【问题描述】:我需要通过线程调用一个类的成员函数,但我不想使用 Boost 库绑定概念,而且我必须使用的类没有任何静态函数来提供帮助。我尝试使用STL mem_fun_ref
,但收到编译时错误。
base b;
handle = CreateThread(NULL, 0, LPTHREAD_START_ROUTINE(bind2nd(mem_fun_ref(&base::show), &b)),
NULL, NULL, &dword);
class B
public:
void show()
cout << "show";
;
【问题讨论】:
你得到的两个答案都是对的,但是注意一般应该使用_beginthreadex()
而不是CreateThread()
,否则CRT可能无法为新线程正确初始化。
【参考方案1】:
我不知道CreateThread()
,但它看起来像是用于创建线程的C 风格接口:您可能无法传递函数对象。最有可能的是,开始函数类型在道德上等同于
extern "C" typedef void (*entry_funciont)(void*);
可能带有一些额外的参数并返回与void
不同的东西。你需要一个转发函数来恢复你的函数对象,你需要知道作为“用户数据”传递给CreateThread()
函数的函数对象的确切类型(我猜你在哪里传递@987654325 @ 在你函数对象之后。你可以使用类似这样的东西:
struct entry_base
virtual ~entry_base()
virtual void call() = 0;
;
template <typename Fun>
struct entry
: entry_base
Fun fun;
entry(Fun fun): d_fun(fun)
void call()
this->d_fun();
delete this;
;
template <typename Fun>
entry_base* make_entry(Fun fun)
return new entry<Fun>(fun);
extern "C" void call_entry(void* entry)
static_cast<entry_base*>(entry)->call();
... 然后可以这样使用:
base* b = ...; // you can't use a local object here!
handle = CreateThread(NULL, 0,
LPTHREAD_START_ROUTINE(&call_entry),
make_entry(bind2nd(mem_fun_ref(&base::show), &b)),
NULL, &dword);
请注意,我在推测CreateThread()
的接口,即用户数据指针很可能会进入不同的位置。但是,绑定到指向本地对象的指针几乎肯定不会起作用:该对象可能会在线程运行时超出范围,并且会删除对象运行的基础。
【讨论】:
创建线程是WinAPI函数,问题标记为winapi。 @IuriCovalisin:是的,我注意到:你并不暗示我必须知道 WinAPI 才能提供我认为有用的东西,对吗?这个问题也被标记为 C++,这就是我遇到它的地方。我认为我的回答确实适用,尽管需要处理一些细节。乍一看,我的猜测实际上都是正确的......【参考方案2】:这是 C WinAPI 函数,声明如下:
HANDLE WINAPI CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
问题在于 LPTHREAD_START_ROUTINE 类型定义了一个指向回调函数的指针,而不是“隐藏”了这个参数的 C++ 方法。
以下是如何绕过它的好例子: http://blogs.msdn.com/b/oldnewthing/archive/2004/01/09/49028.aspx
class SomeClass
...
static DWORD CALLBACK s_ThreadProc(LPVOID lpParameter)
return ((SomeClass*)lpParameter)->ThreadProc();
DWORD ThreadProc()
... fun stuff ...
;
【讨论】:
以上是关于线程调用成员函数的主要内容,如果未能解决你的问题,请参考以下文章