2013-10-05 62 views
0

我需要通過線程調用一個類的成員函數,但我不想使用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"; 
    } 
}; 
+0

的兩個答案你都是對的,但要注意,你通常應該使用'_beginthreadex()'而不是'的CreateThread()',否則對於新線程,CRT可能無法正確初始化。 –

回答

1

我不知道CreateThread(),但看起來像一個C風格的界面來創建線程:你可能不能夠通過一個函數對象。最有可能的啓動功能類型是

extern "C" typedef void (*entry_funciont)(void*); 

道德等同可能與一些額外的參數和返回的東西比void不同。你需要一個轉發函數來恢復你的函數對象,你需要知道傳遞給CreateThread()函數的函數對象的確切類型,作爲「用戶數據」(我猜你在哪裏通過NULL 。函數對象你可以使用沿此線的東西:

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(),即用戶數據指針可能會進入不同的位置,但是,綁定到一個指針ter本地對象幾乎肯定不會起作用:在線程運行時,該對象可能會超出範圍,並且會刪除該對象運行的基礎。

+0

創建線程是WinAPI函數,問題標記爲winapi。 –

+0

@IuriCovalisin:是的,我注意到:你並不意味着我必須知道WinAPI才能提供我認爲有用的東西,對嗎?這個問題也被標記爲C++,這就是我遇到它的地方。我*認爲*我的答案確實適用,但一些細節需要干預。從cusory看來,我的猜測其實都是正確的...... –

1

這是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 ... 
} 
};