2014-04-01 37 views
0

我已經工作WinAPI的一段時間,我發現每當我嘗試使用WINAPI功能(如創建按鈕/窗/更新列表視圖和等)線程這裏面ISN主線程,它不會出現。例如,如果我想將項目添加到ListView,並且我調用一個接受字符串並將其添加到列表視圖的函數,如果我從主線程調用該函數,它將工作得很好,但如果我從不同的線程調用它,它根本就不起作用。與WINAPI正與幾個線程

我該怎麼辦?

+0

你可以顯示一些代碼。並定義「根本不會工作」。 –

回答

4

與大多數(全部?)GUI系統需要更新從擁有該窗口(通常是主線程)的線程的GUI。你需要找到一種在兩個線程之間進行通信的方法。在Win32中,我的首選方法是將user message發送到GUI線程(通過PostMessage)並相應地更新。您需要確保不會同時訪問您在它們之間發送的數據,例如使用關鍵部分或其他來保護全局數據。

一個簡單的例子,半僞代碼:

#define WM_MY_MESSAGE WM_USER+1 

thread 
{ 
    do some number crunching... 
    // inform user 
    EnterCriticalSection(&MessageCrit); 
    strncpy(StatusMessageText, "Crunching away...", ARRAYSIZE(StatusMessageText)); 
    LeaveCriticalSection(&MessageCrit); 
    PostMessage(hwndMain, WM_MY_MESSAGE, 0, 0); // You can utilize the params to your hearts content: structures, enums, etc... 
} 

guithread 
{ 
switch (message) 
{ 
case WM_INITDIALOG: // etc - whatever is in your normal message handler 
    break; 
case WM_MY_MESSAGE: 
    ListView_InsertItem(...); // etc 
    EnterCriticalSection(&MessageCrit); // Protect the global data 
    ListView_SetItemText(item, StatusMessageText); 
    LeaveCriticalSection(&MessageCrit);  
    break; 
} 
} 
+1

我不認爲它必須是* main *線程。它只是創建組件的線程,或者可能是包含消息泵的線程。 –

+1

實際上,向其他線程上的窗口發送消息*是可能的,並且*是在Windows上執行線程間通信的方式。將消息發佈給線程,然後將相同的消息發佈到窗口,這是多餘的。但是,例如不可能在另一個線程的窗口作爲其父窗口的線程上創建一個窗口。 – jlahd

+0

然後,如果我想通過不同的線程將一個項目添加到列表視圖中,我在PostMessage函數中編寫了什麼? – Amit

0

您應該使用PostMessage

static LVITEM lvi = { ... }; 
PostMessage(myListView, LVM_INSERTITEM, 0, (LPARAM)&lvi); 

,或者如果需要返回值,首先要建立你的線程消息泵:

MSG msg; 
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE); 
static LVITEM lvi = { ... }; 
ListView_InsertItem(myListView, &lvi); 

如果您使用PostMessage,一定要保持內存還活着當PostMessage返回,因爲消息是由主線程異步處理的。

+0

我不明白你爲什麼要用'PostMessage'和'LVM_INSERTITEM'。你能解釋一下爲什麼。 –

+0

在主窗口線程處理消息期間不阻止發佈線程。 – jlahd

+0

但是這樣做會給你帶來'LVITEM'結構的巨大的生命週期管理問題。 –