定时器与多线程 SetTimer and Multi-Thread 每个线程独立使用一个定时器

生产者——消费者 模拟程序,需求如下:

  将生产者和消费者模拟算法封装在一个动态链接库中,主程序调用相关函数。生产者放入产品和消费者取走产品的速度可调节。
分别用循环队列和栈实现。

一般模拟这个算法都是生产这,消费者各开一个线程,同步访问一个共享缓冲区。但是需求要求能调节速度,我的思路是在
每个线程里单独创建一个定时器,但是Windows下定时器特性是:
   每隔定时时间,Windows系统放入一个 WM_TIMER 消息到应用程序的消息队列中。

所以我的解决方案如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/* 更改定时器的消息 */
#define WM_SETTIMER WM_USER + 100
/* 生产者线程函数 */
DWORD WINAPI ProducerFunc( LPVOID lpParameter)
{
     MSG msg;
     UINT producerTimerId;
     /* Create a message queue for this thread */
     PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
     producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL);
     while (GetMessage(&msg, NULL, 0, 0))
     {
         if (msg.message == WM_TIMER)
         {
             WaitForSingleObject(g_hEmptySemaphore, INFINITE);
             WaitForSingleObject(g_hMutex, INFINITE);
             Producer();
             ReleaseMutex(g_hMutex);
             ReleaseSemaphore(g_hFullSemaphore, 1, NULL);
         }
         else if (msg.message == WM_SETTIMER)
         {
             KillTimer(NULL, producerTimerId);
             producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL);
         }
         else
         {
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         }
     }
     KillTimer(NULL, producerTimerId);
     return 0;
}
/* 消费者线程函数 */
DWORD WINAPI ConsumerFunc( LPVOID lpParameter)
{
     MSG msg;
     UINT consumerTimerId;
     PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
     consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL);
     while (GetMessage(&msg, NULL, 0, 0))
     {
         if (msg.message == WM_TIMER)
         {
             WaitForSingleObject(g_hFullSemaphore, INFINITE);
             WaitForSingleObject(g_hMutex, INFINITE);
             Consumer();
             ReleaseMutex(g_hMutex);
             ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);
         }
         else if (msg.message == WM_SETTIMER)
         {
             KillTimer(NULL, consumerTimerId);
             consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL);
         }
         else
         {
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         }
     }
     KillTimer(NULL, consumerTimerId);
     return 0;
}

---------------------------------------------------------------------------

子线程里如何使用定时器 摘自CSDN


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
UINT_PTR   hTimer   =   0;  
   //定时器消息处理函数  
   VOID   __stdcall   TimerProc( HWND   hwnd, UINT   uMsg, UINT_PTR   idEvent, DWORD   dwTime)  
   {  
   KillTimer(NULL,hTimer);  
   MessageBox(NULL, "Speak   in   Timer!" , ":)" ,MB_OK);  
   }  
     
   //线程函数  
   DWORD   __stdcall   ThreadFun( void   *)  
   {  
   MSG   msg;  
   PeekMessage(&msg,   NULL,   NULL,   NULL,   PM_NOREMOVE);  
   hTimer   =   SetTimer(NULL,0,10,(TIMERPROC)TimerProc);  
   while (!PeekMessage(&msg,NULL,WM_TIMER,WM_USER+1,PM_NOREMOVE))  
   {  
   OutputDebugString( "Not   peek   message\r\n" );  
   Sleep(100);  
   }  
   if (msg.message   ==   (WM_USER+1))  
   {  
                                       //收到主线程发来的消息  
   OutputDebugString( "Rec   message\r\n" );  
   }  
   else  
   {  
                                       //收到定时器消息,派送之  
   OutputDebugString( "what   message\r\n" );  
   DispatchMessage(&msg);  
   }  
   return   0;  
   }  
     
     
   //创建线程代码:  
   DWORD   dwThreadId;    
           HANDLE   hThread   =   NULL;  
   hThread   =   CreateThread(NULL,0,ThreadFun,NULL,0,&dwThreadId);  
   if   (hThread   ==   NULL)    
   {  
   MessageBox( "CreateThread   failed." ,   "main" ,   MB_OK   );  
   }  
   else    
   {  
   OutputDebugString( "prepare   post   message\r\n" );  
   Sleep(1000); //等待线程创建好了  
   PostThreadMessage(dwThreadId,WM_USER+1,0,0); //给线程发消息  
   OutputDebugString( "Post   message   ok\r\n" );  
   CloseHandle(   hThread   );  
   }

  你把PostThreadMessage(dwThreadId,WM_USER+1,0,0);注释掉就可以收到定时器消息了,或者是你在线程里循环的接收消息,否则只能接收到一条。


 这是MFC的CWinThread类的实现。   首先创建一个线程   _beginthread(MainThread,   DEFAULT_STACK_SIZE,   NULL);   
  然后在MainThread中创建一个看不见的窗口(伪窗口):   
   

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
WNDCLASS   wcl;  
   HWND   hWnd   =   NULL;  
     
   memset (&wcl,0, sizeof (wcl));  
     
   if   (lpfnWndProc   ==   NULL)  
   {  
   return     NULL;   /*失败*/  
   }  
     
   /*register   class*/    
     
   wcl.cbClsExtra   =   0;  
   wcl.cbWndExtra   =   0;  
   wcl.hbrBackground   =   NULL;  
   wcl.hCursor   =   NULL;  
   wcl.hIcon   =   NULL;  
   wcl.hInstance   =   NULL;  
   wcl.lpfnWndProc   =   MainWindowProc;  
   wcl.lpszClassName   =   szWndName;  
   wcl.lpszMenuName   =   NULL;  
   wcl.style   =   CS_VREDRAW;  
   if   (RegisterClass(&wcl)   ==   0)  
   {  
   return   NULL;  
   }  
     
   /*create   window*/  
   hWnd   =   CreateWindow(szWndName,NULL,WS_POPUP,0,0,  
   CW_USEDEFAULT,CW_USEDEFAULT,  
   NULL,NULL,NULL,NULL);  
     
   /*进入消息循环*/  
           do  
           {  
                   ret   =   GetMessage(&msg,NULL,0,0);  
                   if   (ret   >   0)  
                   {  
                           DispatchMessage(&msg);  
                   }  
     
           } while (ret   >   0);  
     
     
   DestroySTUNServerWindow(szWndName,   s_hSTUNServerWnd);  
   最后可以在MainWindowProc中处理你的消息了:  
   LRESULT   CALLBACK   MainWindowProc( HWND   hWnd,  
         UINT   uMsg,      
         WPARAM     wParam,  
         LPARAM   lParam)  
   {  
   switch (uMsg)  
           {  
   default :  
   return   DefWindowProc(hWnd,uMsg,wParam,lParam);  
   }  
     
   return   0;  
   }  
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值