C++ 線程的創建、掛起、喚醒和結束 &&&& 利用waitForSingleObject 函數陷入死鎖的問題解決


最近在寫一個CAN總線的上位機軟件,利用CAN轉USB的設備連到電腦上,進行數據的傳輸。在接收下位機發送的數據的時候采用的在線程中持續接收數據。

1、在連接設備的函數中,開啟線程。

//在創建線程的時候,將線程掛起,掛起的線程可設置下面的m_bAutoDelete 等屬性,再進行線程的喚醒

m_pThread = AfxBeginThread(ReceiveThread,this,0,CREATE_SUSPENDED,NULL);
m_pThread->m_bAutoDelete = false;

2、線程喚醒

ResumeThread(m_pThread->m_hThread);

3、線程掛起

SuspendThread(m_pThread->m_hThread);

4、線程結束

線程結束呢,網上最推薦的方法是線程函數正常返回,即某個變量達到某個標准,退出循環,結束線程。

UINT CTest_OilDlg::ReceiveThread(void *param)
{
    while(1)
    {
        Sleep(1);
        if(dlg->m_connect == 0)
        {
            break;
        }
                //   其他操作
     }
}             

上面滿足m_connect == 0,即設備斷開該循環就結束,線程函數就會進行正常返回。在結束線程的地方寫如下代碼

::WaitForSingleObject(m_pThread->m_hThread,INFINITE);
delete m_pThread;
m_pThread = NULL;//不太懂
WaitForSingleObject該函數是等待線程運行結束,即線程結束后置空線程。但是在使用該函數的時候,子線程里面不能有更新界面的操作,比如更新某個控件。因為這個函數是個阻塞函數,不僅阻塞線程也會阻塞消息。也就是說該函數要等待線程結束,而線程中如果有更新界面的操作,則需要界面的這個主線程給一個反應,但是此時界面的主線程被waitForSingleObject函數阻塞着,也就是進入了一個死鎖的境遇。
這個時候可以改用MsgWaitForMultipleObjects這個函數,這個函數是微軟針對waitForSingleObject會阻塞消息給出的一個函數,MsgWaitForMultipleObjects不會阻塞消息。
也就是上面的代碼可以改寫成如下:
    
DWORD dwRet = 0;
            MSG msg;
            while(true)
            {
                //等待處理數據線程結束,和等待消息隊列中的任何消息
                dwRet = MsgWaitForMultipleObjects(1,&m_pThread->m_hThread,false,INFINITE,QS_ALLINPUT);
                //dwRet = WaitForSingleObject(m_pThread->m_hThread,50);
                switch (dwRet)
                {
                case WAIT_OBJECT_0:
                        break;
                case WAIT_OBJECT_0 + 1:
                    //get the message from Queue and dispatch it to specific window
                    PeekMessage(&msg,NULL,0,0,PM_REMOVE);
                    DispatchMessage(&msg);
                    continue;
                default:
                    break;
                }
                break;
            }
            //CloseHandle(m_pThread->m_hThread);
            delete m_pThread;
            m_pThread = NULL;//不太懂

 

關於WaitForMultipleObjects(參考https://www.cnblogs.com/shangdawei/p/4015772.html

DWORD WaitForMultipleObjects(
DWORD dwCount, //等待的內核對象個數
CONST HANDLE* phObjects, //一個存放被等待的內核對象句柄的數組
BOOL bWaitAll, //是否等到所有內核對象為已通知狀態后才返回
DWORD dwMilliseconds); //等待時間
HANDLE h[3]; //句柄數組
//三個進程句柄
h[0] = hProcess1;
h[1] = hProcess2;
h[2] = hProcess3;
DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); //等待3個進程結束
switch (dw)
{
  case WAIT_FAILED:
  // 函數呼叫失敗
  break;
   
  case WAIT_TIMEOUT:
  // 超時
  break;
   
  case WAIT_OBJECT_0 + 0:
  // h[0](hProcess1)所代表的進程結束
  break;
   
  case WAIT_OBJECT_0 + 1:
  // h[1](hProcess2)所代表的進程結束
  break;
   
  case WAIT_OBJECT_0 + 2:
  // h[2](hProcess3)所代表的進程結束
  break;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM