關於RegisterWaitForSingleObject函數的使用總結

在尋找前一篇文章中google breakpad的用法時,看到了關於windows函數RegisterWaitForSingleObject的用法,感覺還不錯,而且在百度上面直接搜索RegisterWaitForSingleObject,出來的信息沒怎麼找到C++的,於是現在就來總結一下(水個博客)。RegisterWaitForSingleObject的詳細介紹在https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-registerwaitforsingleobject

RegisterWaitForSingleObject函數原型如下:

BOOL RegisterWaitForSingleObject(
  PHANDLE             phNewWaitObject,
  HANDLE              hObject,
  WAITORTIMERCALLBACK Callback,
  PVOID               Context,
  ULONG               dwMilliseconds,
  ULONG               dwFlags
);

事實上,按照MSDN的說法,這個函數的作用相當於開了一條新線程,在該線程裏面等待hObject的結束或dwMilliseconds超時後,按照dwFlags的要求執行Callback函數,傳遞Context作爲參數而已,經常使用windows函數的程序員應該很容易就看出來了。

但是,還是有要注意的事項的:

  1. 關於phNewWaitObject,這個句柄在MSDN中明確說明了A pointer to a variable that receives a wait handle on return. Note that a wait handle cannot be used in functions that require an object handle, such as CloseHandle.即不可以通過CloseHandle直接關閉該句柄,必須使用UnregisterWait或者UnregisterWaitEx來關閉該句柄,即使使用WT_EXECUTEONLYONCE 也要這樣子來取消註冊。
  2. 關於hObject,在不使用WT_EXECUTEONLYONCE或者WT_EXECUTEINWAITTHREAD時,不要註冊等待一直處於有信號狀態的句柄,否則回調函數會執行很多次,直到改句柄變爲無信號爲止。
  3. 還是關於hObject的,如果在等待仍未完成的情況下關閉此句柄,則該函數的行爲是未定義的。這也很容易理解,例如一個線程在等待hMutex,另一個線程在佔用hMutex並直接關閉了,前一個線程就GG了。
  4. 關於UnregisterWaitEx的使用請查看該網址:https://docs.microsoft.com/zh-cn/windows/win32/sync/unregisterwaitex

其它注意的事項可以繼續參閱前面的MSDN中關於該函數的網址。

下面貼一個本人在VS2017上使用該函數的小例子:

#include <Windows.h>
#include <thread>
#include <iostream>
    
VOID NTAPI WaitForThreadExit(PVOID, BOOLEAN)
{
    std::cout << "thread exit" << std::endl;
}

int test()
{
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 0;
}


int main()
{
    
    std::thread t(test);

    HANDLE hWait = NULL;
    if (RegisterWaitForSingleObject(&hWait, t.native_handle(), WaitForThreadExit, NULL, INFINITE, WT_EXECUTEONLYONCE) == FALSE)
    {
        std::cout << "RegisterWaitForSingleObject fail, GetLastError " << GetLastError() << std::endl;
    }
    t.detach();

    system("pause");

    if (hWait != NULL)
    {
        UnregisterWaitEx(hWait, INVALID_HANDLE_VALUE);
        hWait = NULL;
    }

    return 0;
}

以上就是本博客的全文,本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章