最近在寫一個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; }
