簡體   English   中英

MFC:如何在主線程中使用 MsgWaitForMultipleObjects() 來等待多個線程完成使用 SendMessage()?

[英]MFC: How to use MsgWaitForMultipleObjects() from the main thread to wait for multiple threads to complete that use SendMessage()?

我有一個主線程,它會觸發其他幾個線程,以根據用戶從主 UI 中選擇的內容來完成各種工作。 通常我會使用WaitForMultipleObjects()並將bWaitAll設置為 TRUE。 但是,在這種情況下,其他線程會將 output 記錄到另一個使用互斥鎖的 window 以確保線程一次只有一個 output。 該過程的一部分使用SendMessage()發送獲取文本大小並將文本發送到 windows,如果使用WaitForMultipleObjects()將掛起,因為它是從主 UI 線程運行的。 所以我轉而使用帶有QS_SENDMESSAGE標志的MsgWaitForMultipleObjects ,唯一的問題是bWaitAll的邏輯,它指出只有在所有對象都發出信號並且發生輸入事件時才會返回(而不是在所有對象發出信號發生輸入事件時返回) . 如果邏輯是OR這應該有效:

  DWORD waitres=WAIT_FAILED;

  while (1)
  {
    MSG msg;
    while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
      // mfc message pump
      if (!theApp.PumpMessage()) {
        // program end request
        // TO DO
      }
    }
    // MFC idel processing
    LONG lidlecount = 0;
    while (theApp.OnIdle(lidlecount++));
    // our wait
    waitres = ::MsgWaitForMultipleObjects(threadcount, threadhandles, TRUE, INFINITE, QS_SENDMESSAGE);
    // check if ended due to message
    if (waitres!=WAIT_OBJECT_0+threadcount) {
      // no, exit loop
      break;
    }
  }

而不是觸發一個線程然后觸發其他線程我想知道從主線程處理這個問題的正確方法是什么? 我考慮過使用bWaitAll FALSE 然后使用WaitForMultipleObjects()並將bWaitAll設置為 TRUE 並將dwMilliseconds設置為 0(或 1)並檢查結果以查看是否完成。 如果沒有,它需要循環回到循環的頂部,然后再循環MsgWaitForMultipleObjects() ,如果多個線程之一完成(比如 10 個線程中的一個完成,我可以檢查如前所述以上如果全部完成,但當返回bWaitAll FALSE 時,它只會返回而不等待)。

那么在 MFC 應用程序的主線程中處理等待多個線程(使用SendMessage() )完成的正確方法是什么?

謝謝。

那么處理等待多個線程完成的正確方法是什么

需要創建一些具有引用計數的結構並將指向該結構的指針傳遞給每個線程。 這里也可能存在意義有一些常見的任務數據。 和主(GUI)線程中一些 window 的HWND 當工作線程退出時 - 它釋放 object 上的參考。 當最后一個線程退出時 - 刪除 object 並從主線程向 window 發布一些消息。

所以我們不需要存儲線程句柄(可以關閉它)並等待多個句柄。 相反,當所有線程完成任務時,我們收到了一些 window 消息

代碼示例

struct Task 
{
    HWND _hwnd;
    LONG _dwRefCount = 1;
    // some common task data probably ..

    Task(HWND hwnd) : _hwnd(hwnd) {}

    ~Task() {
        PostMessageW(_hwnd, WM_USER, 0, 0);// WM_USER as demo only
    }

    void AddRef(){
        InterlockedIncrementNoFence(&_dwRefCount);
    }

    void Release(){
        if (!InterlockedDecrement(&_dwRefCount)) delete this;
    }
};

ULONG CALLBACK WorkThread(void* pTask)
{
    WCHAR sz[16];
    swprintf_s(sz, _countof(sz), L"%x", GetCurrentThreadId());
    MessageBoxW(0, L"working...", sz, MB_ICONINFORMATION|MB_OK);
    reinterpret_cast<Task*>(pTask)->Release();
    return 0;
}

void StartTask(HWND hwnd, ULONG n)
{
    if (Task* pTask = new Task(hwnd))
    {
        do 
        {
            pTask->AddRef();

            if (HANDLE hThread = CreateThread(0, 0, WorkThread, pTask, 0, 0))
            {
                CloseHandle(hThread);
            }
            else
            {
                pTask->Release();
            }
        } while (--n);

        pTask->Release();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM