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回调无法执行!

问题分析:

CreateTimerQueueTimerDeleteTimerQueueTimer 分别负责线程的开启和中止,函数定义如下:

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()调用中结束调用。由于DeleteTimerQueueTimerCompletionEvent中使用的是INVALID_HANDLE_VALUE,导致线程会等待所有timer线程执行结束,才能返回。而当前执行回调的线程等不到自己结束,陷入死锁。因为CreateTimerQueueTimerFlag参数使用的是WT_EXECUTEINTIMERTHREAD导致test1回调和test使用的是同一线程,而test线程已经死锁,所以test1也无法得到执行

解决方案:

  1. 不应该在回调中调用DeleteTimerQueueTimer中止线程
  2. 如果必须在回调中中止线程,CompletionEvent应设为NULL,标记当前线程结束后,直接返回0(执行失败),回调执行完,不再继续执行
  3. CreateTimerQueueTimer使用Flag WT_EXECUTEDEFAULT开启新线程,即使上一个timer线程死锁,第二个线程仍可以执行

 

热门相关:恭喜你被逮捕了   我的嫂子   后福   买妻种田:山野夫君,强势宠!   大妆