我已經工作WinAPI的一段時間,我發現每當我嘗試使用WINAPI功能(如創建按鈕/窗/更新列表視圖和等)線程這裏面ISN主線程,它不會出現。例如,如果我想將項目添加到ListView,並且我調用一個接受字符串並將其添加到列表視圖的函數,如果我從主線程調用該函數,它將工作得很好,但如果我從不同的線程調用它,它根本就不起作用。與WINAPI正與幾個線程
我該怎麼辦?
我已經工作WinAPI的一段時間,我發現每當我嘗試使用WINAPI功能(如創建按鈕/窗/更新列表視圖和等)線程這裏面ISN主線程,它不會出現。例如,如果我想將項目添加到ListView,並且我調用一個接受字符串並將其添加到列表視圖的函數,如果我從主線程調用該函數,它將工作得很好,但如果我從不同的線程調用它,它根本就不起作用。與WINAPI正與幾個線程
我該怎麼辦?
與大多數(全部?)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;
}
}
您應該使用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
返回,因爲消息是由主線程異步處理的。
我不明白你爲什麼要用'PostMessage'和'LVM_INSERTITEM'。你能解釋一下爲什麼。 –
在主窗口線程處理消息期間不阻止發佈線程。 – jlahd
但是這樣做會給你帶來'LVITEM'結構的巨大的生命週期管理問題。 –
你可以顯示一些代碼。並定義「根本不會工作」。 –