2013-02-18 101 views
1

在將項目遷移到帶有msvc110的C++ 11標準的過程中,不幸的是,在dll上使用的線程變量與我的boost版本有所不同。C++ 11線程vs升級線程

所以,最初這是在msvc90上工作,基本上Dll調用一個線程創建的InitDll。 該線程基本上作爲一個監聽程序以及dll的主線程。 現在,當我創建線程時,它掛起並不執行任何操作,甚至不執行用於初始化線程的函數。

你能幫我解釋我怎麼能得到與升壓版相同的行爲?

編輯:CODE

很抱歉,無法回覆的評論

應用程序使用記錄器通過一個DLL的代碼。 要在一個非常簡單的控制檯應用程序使用記錄是這樣的

#include <Somewhere/Logger.h> 

int main() 
{ 
    COOL_LOGGER("Here we go logging on console!"); 

return 0; 
} 

我們可以對代碼的編寫方式(從演示我提到拍攝)討論,但如何初始化DLL和線程是:

#include "Logger.h" 

#ifdef _WIN32 

BOOL APIENTRY DllMain(HMODULE hModule, 
        DWORD ul_reason_for_call, 
        LPVOID lpReserved 
       ) 
{ 
switch (ul_reason_for_call) 
{ 
    case DLL_PROCESS_ATTACH: 
    TheLog::InitLog(); 
      break; 
    case DLL_THREAD_ATTACH: 
    break; 
     case DLL_THREAD_DETACH: 
    break; 
    case DLL_PROCESS_DETACH: 
    break; 
} 
    return TRUE; 
} 

#endif 


#include <thread> 

void InitLog() 
{ 
// Do the init taken from library demos 
std::thread m_thread(LogListener); 
} 

void LogListener() 
{ 
while(!bAppEnd) 
{ 
    std::cin>>str; 
    // change log behavior according to the user input 
} 
} 


// to stop the thread when shutting down 
void EndLog() 
{ 
    // retrieve thread thought id or some other way 
    thread.join(); 
} 
+2

你應該發佈一些代碼。但是,這聽起來像你可能在'DllMain()'中執行這個init。在DllMain()中執行重要的工作是一項非常危險的工作。請參閱文檔的註釋部分:http://msdn.microsoft.com/en-us/library/ms682583.aspx和http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/ 63401.aspx或http://blogs.msdn.com/b/oldnewthing/archive/2004/01/28/63880.aspx – 2013-02-18 18:26:20

+0

謝謝Micheal,非常真實。我讀過關於在DllMain上做些花哨的東西,不管我在這裏是否真的發明過輪子。我只是將代碼作爲日誌庫的示例dll_and_exe的參考http://torjo.com/log2/doc/html/index.html – notNullGothik 2013-02-18 22:29:32

+0

自從我在前面實現它之後,沒有改變任何特定行爲,它迄今爲止工作很好。你會推薦我初始化圖書館的正確方法嗎?我記得有點掙扎,試圖從DLLMain中刪除init並將它調用到其他地方,如果我記得確切的問題,會發布更多。 – notNullGothik 2013-02-18 22:32:03

回答

2

您的InitLog函數有一個線程,該線程顯示爲該函數的作用域。當函數退出時,它立即執行,線程被銷燬。但是,破壞一個未加入的std :: thread(但不是boost :: thread?)會調用std :: terminate。如果你想測試那是發生了什麼,請加入終止處理程序。

+0

我相信最近版本的Boost.Thread [對齊](http://stackoverflow.com/q/11393936/283302)一個unjoined'std :: thread'的行爲 – 2013-02-19 02:40:07

+0

沒錯,舊版本不太確定,考慮到OP提到VS 9.0(aka 2005),Boost也可能是舊版本。 – metal 2013-02-19 02:47:22

+0

我照顧有最新的庫與遷移過程,boost_1_53_0 – notNullGothik 2013-02-19 02:54:43

3

如果DllMain出問題了,那麼你在做什麼時會受到嚴重的限制---通常Windows加載器會終止應用程序,並且通常不會調用錯誤處理程序。

掛起表明代碼正在做某些事情需要加載一個DLL,或者正在等待另一個DLL進行初始化,這兩種情況都不會發生,直到完成此DLL的DllMain調用。 std::thread的執行可能正在執行這些操作之一。

編輯:避免此問題的一種方法是在與此後臺線程通信的每個導出函數中使用std::call_once,以確保線程已啓動。這樣你就不會在DllMain中使用std::thread,但是你不需要公開一個「init」函數。

+0

謝謝,似乎是這樣。我會堅持一個來自main的初始化調用,就像我之前在上面的評論中指出的那樣。不想將此泄露給用戶,但我目前看不到解決方法。 – notNullGothik 2013-02-19 15:15:44

+0

您可以使用'std :: call_once',如我的編輯中所述。 – 2013-02-19 15:24:26