定時器與多線程 SetTimer and Multi-Thread 每一個線程獨立使用一個定時器

定時器與多線程 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;
}

--------------------------------------------------------------------------- post

子線程裏如何使用定時器 摘自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中建立一個看不見的窗口(僞窗口):   
    this

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