Windows线程API —CreateTimerQueueTimer/DeleteTimerQueueTimer的使用
问题代码:
1 #include<windows.h> 2 #include<iostream> 3 #include<thread> 4 HANDLE h1; 5 HANDLE h2; 6 7 void CALLBACK test(PVOID a, BOOLEAN b) 8 { 9 std::cout << "This a test function excuted by Thread:" << std::this_thread::get_id()<< std::endl; 10 //std::cout << "Here we try to delete timer in Thread:" << std::this_thread::get_id() << std::endl; 11 if (0 == DeleteTimerQueueTimer(NULL, h1, INVALID_HANDLE_VALUE)) 12 { 13 std::cout << "Timer Deleted Failed in Thread:" << std::this_thread::get_id() << std::endl; 14 } 15 std::cout << "Timer Deleted Successfully in Thread:" << std::this_thread::get_id() << std::endl; 16 17 } 18 void CALLBACK test1(PVOID l, BOOLEAN t) 19 { 20 std::cout << "This a test1 function excuted by Thread:" << std::this_thread::get_id() << std::endl; 21 } 22 23 int main() 24 { 25 26 std::cout << "******This is a Test for TimeQueueTimer in Windows API******" << std::endl; 27 std::cout << "Main thread is executed by thread: " << std::this_thread::get_id() << std::endl; 28 //test(PVOID(1), TRUE); 29 try 30 { 31 CreateTimerQueueTimer(&h1, NULL, WAITORTIMERCALLBACK(test), NULL, 0, 1000, WT_EXECUTEINTIMERTHREAD); 32 //Sleep(1000); 33 34 CreateTimerQueueTimer(&h2, NULL, WAITORTIMERCALLBACK(test1), NULL, 0, 1000, WT_EXECUTEINTIMERTHREAD); 35 36 37 //CreateTimerQueueTimer(&h1, NULL, [](PVOID lpParameter, BOOLEAN TimerOrWaitFired) { 38 // test(lpParameter, TimerOrWaitFired); // Call your original test function from within the lambda 39 // }, NULL, 0, 1000, WT_EXECUTEINTIMERTHREAD); 40 41 } 42 catch (const std::exception& e) 43 { 44 std::cout << "something error with the timer: " << e.what() << std::endl; 45 } 46 47 48 if (std::cin.get()) 49 { 50 if (0 == DeleteTimerQueueTimer(NULL, h2, INVALID_HANDLE_VALUE)) 51 { 52 std::cout << "Timer Deleted Failed in Thread:" << std::this_thread::get_id() << std::endl; 53 } 54 std::cout << "Timer Deleted Successfully in Thread:" << std::this_thread::get_id() << std::endl; 55 56 }; 57 Sleep(1000); 58 59 return 0; 60 }
Main()函数中test1回调无法执行!
问题分析:
CreateTimerQueueTimer和DeleteTimerQueueTimer 分别负责线程的开启和中止,函数定义如下:
BOOL CreateTimerQueueTimer( [out] PHANDLE phNewTimer, [in, optional] HANDLE TimerQueue, [in] WAITORTIMERCALLBACK Callback, [in, optional] PVOID Parameter, [in] DWORD DueTime, [in] DWORD Period, [in] ULONG Flags );
BOOL DeleteTimerQueueTimer( [in, optional] HANDLE TimerQueue, [in] HANDLE Timer, [in, optional] HANDLE CompletionEvent );
主线程中分别利用CreateTimerQueueTimer开启后台线程调用回调test()和test1(),并在test()调用中结束调用。由于DeleteTimerQueueTimer中CompletionEvent中使用的是INVALID_HANDLE_VALUE,导致线程会等待所有timer线程执行结束,才能返回。而当前执行回调的线程等不到自己结束,陷入死锁。因为CreateTimerQueueTimer的Flag参数使用的是WT_EXECUTEINTIMERTHREAD,导致test1回调和test使用的是同一线程,而test线程已经死锁,所以test1也无法得到执行
解决方案:
- 不应该在回调中调用DeleteTimerQueueTimer中止线程
- 如果必须在回调中中止线程,CompletionEvent应设为NULL,标记当前线程结束后,直接返回0(执行失败),回调执行完,不再继续执行
- CreateTimerQueueTimer使用Flag WT_EXECUTEDEFAULT开启新线程,即使上一个timer线程死锁,第二个线程仍可以执行
热门相关:恭喜你被逮捕了 我的嫂子 后福 买妻种田:山野夫君,强势宠! 大妆