2017-01-18 65 views
0

我需要例如運行:的ShellExecute在_beginthread

ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE); 

爲新的線程,但我不知道怎麼辦。 我嘗試這樣做:

HANDLE hThread = (HANDLE) _beginthread(ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE), 0, NULL); 
WaitForSingleObject(hThread, INFINITE); 

但很明顯這是錯誤的,不能進行編譯。我應該怎麼做?

+3

你不太可能需要一個新的線程。 'ShellExecute'是異步的。它會立即返回。它不會阻止其他進程。如果你正在開始一個新的進程,無論如何'CreateProcess'通常是最好的。如果你想在一個新的線程中執行它,用這個簽名'void(__cdecl * start_address)(void *)'創建一個調用'ShellExecute'的函數。然後將該函數傳遞給'_beginthread'。如果你使用C++,那麼肯定會使用'std :: thread'更有意義。 –

+2

你想在自己的線程中運行'ShellExecute'(或'ShellExecuteEx')的唯一原因是,你需要在該線程上初始化COM,並且它可能會與調用線程的公寓發生衝突。但是,你甚至沒有嘗試這麼做,所以完全不清楚,爲什麼你認爲你需要啓動一個線程,然後阻止它完成執行。這沒有實現任何有用的東西。 – IInspectable

回答

3

你試過的確實是錯的,但問題是你是否明白它有什麼問題。 _beginthread指針指向功能(具有特定的原型和調用約定)作爲其第一個參數。

當你寫

HANDLE hThread = (HANDLE) _beginthread(ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE), 0, NULL); 

你試圖通過_beginthread調用ShellExecute(在當前線程)的結果這是一個HINSTANCE,而_beginthread期望一個void(__cdecl *)(void *)(指針__cdecl功能取一個void*參數並返回void)。

不僅你的代碼不工作,因爲你想通過一個HINSTANCE,其中一個函數指針是預期的,它沒有任何意義。你讀過_beginthread documentation嗎?那裏有例子。複數。

你的意思寫的是:

HANDLE hThread = (HANDLE) _beginthread(ThreadFunc, 0, NULL); 

給出:

void __cdecl ThreadFunc(void*) { 
    ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE); 
} 

或者,在更緊湊,更容易閱讀的形式:

HANDLE hThread = (HANDLE) 
       _beginthread([](void*) { 
        ShellExecute(NULL, "open", "program.exe", NULL, NULL, SW_HIDE); 
       }, 
       0, NULL); 

除非你是做一些讓我們在這裏看到的東西,大衛的評論可能是對的,你應該使用std::threadstd::async

另請注意,如文檔中所述,將_beginthread(int對比於_beginthreadexCreateThread的結果)的結果不安全,因爲它可能無效。不僅如此,但_beginthread的返回值是不是一個真正的HANDLE(這是一個手柄的一些疼痛,但不是HANDLE!),所以你不能WaitForSingleObject它:

_beginthreadex功能使您可以更好地控制線程的創建方式,而不是_beginthread_endthreadex功能也更加靈活。例如,使用_beginthreadex,您可以使用安全信息,設置線程的初始狀態(正在運行或掛起),並獲取新創建線程的線程標識符。 您也可以使用_beginthreadex與同步API返回的線程句柄,但不能使用_beginthread

使用_beginthreadex_beginthread更安全。如果由_beginthread生成的線程快速退出,則返回給調用者_beginthread的句柄可能無效或指向另一個線程。然而,由_beginthreadex返回的句柄必須由_beginthreadex的調用者關閉,因此如果_beginthreadex未返回錯誤,它將保證爲有效句柄。

由於此線程只調用一個函數並退出,它幾乎最大化該句柄無效的機會。即使它是,你仍然無法使用它WaitForSingleObject

+0

'ThreadFunc'定義以及lambda函數都缺少相應的調用約定。更重要的是,這個答案甚至沒有質疑是否需要啓動一個新的線程,儘管問題中絕對沒有表明這是有益的。 – IInspectable

+0

['_cdecl'是MSVC中的默認調用約定](https://msdn.microsoft.com/zh-cn/library/zkwh89ks.aspx)。我認爲這是常識,但也許我錯了。雖然這不是明確說明的情況,但由於OP使用的是MSVC CRT的一個功能,我推斷他使用MSVC或兼容的編譯器和工具鏈。 – conio

+0

答案並不質疑創建一個新線程的必要性,原因有三:(1)**答案**不是用於此目的的地方,而是**評論**區域,確實已用於它; (2)與答案無關,並且(3)OP聲明他「需要[s]運行**例子**:'ShellExecute(...)'」。例如。也許他真的想要運行別的東西。也許他執行各種任務,這只是其中之一。那是一個**例子**。 **忽略示例**的一般化問題是如何在新線程上調用函數。我回答。 – conio