在尋找前一篇文章中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函數的程序員應該很容易就看出來了。
但是,還是有要注意的事項的:
- 關於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 也要這樣子來取消註冊。
- 關於hObject,在不使用WT_EXECUTEONLYONCE或者WT_EXECUTEINWAITTHREAD時,不要註冊等待一直處於有信號狀態的句柄,否則回調函數會執行很多次,直到改句柄變爲無信號爲止。
- 還是關於hObject的,如果在等待仍未完成的情況下關閉此句柄,則該函數的行爲是未定義的。這也很容易理解,例如一個線程在等待hMutex,另一個線程在佔用hMutex並直接關閉了,前一個線程就GG了。
- 關於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;
}
以上就是本博客的全文,本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。