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

来源:互联网 发布:炒股哪个软件排名 编辑:程序博客网 时间:2024/05/20 22:04

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

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

一般模拟这个算法都是生产这,消费者各开一个线程,同步访问一个共享缓冲区。但是需求要求能调节速度,我的思路是在
每个线程里单独创建一个定时器,但是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
/* 生产者线程函数 */
DWORDWINAPI ProducerFunc(LPVOIDlpParameter)
{
    MSG msg;
    UINTproducerTimerId;
    /* 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);
        }
        elseif(msg.message == WM_SETTIMER)
        {
            KillTimer(NULL, producerTimerId);
            producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL);
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    KillTimer(NULL, producerTimerId);
    return0;
}
/* 消费者线程函数 */
DWORDWINAPI ConsumerFunc(LPVOIDlpParameter)
{
    MSG msg;
    UINTconsumerTimerId;
    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);
        }
        elseif(msg.message == WM_SETTIMER)
        {
            KillTimer(NULL, consumerTimerId);
            consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL);
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    KillTimer(NULL, consumerTimerId);
    return0;
}

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

子线程里如何使用定时器 摘自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 0
原创粉丝点击