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

旧城冷巷雨未停 提交于 2020-03-01 11:12:46

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

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

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

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

所以我的解决方案如下:

/* 更改定时器的消息 */
#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


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中创建一个看不见的窗口(伪窗口):   
   

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;   
  }

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!