c++ 知識點 : 執行緒相關
阿新 • • 發佈:2018-12-10
1、執行緒開始事件、執行緒結束事件、WaitForMultipleObjects 控制執行緒
假如執行緒是無限迴圈的,需要從執行緒外部控制執行緒結束
//用於執行緒管理的兩事件 //HANDLE CreateEventA( // LPSECURITY_ATTRIBUTES lpEventAttributes, // BOOL bManualReset, // BOOL bInitialState, // LPCSTR lpName // ); // create a "loopback capture has started" event HANDLE hStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStartedEvent) { printf("CreateEvent failed: last error is %u\n", GetLastError()); return -__LINE__; } // create a "stop capturing now" event HANDLE hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == hStopEvent) { printf("CreateEvent failed: last error is %u\n", GetLastError()); CloseHandle(hStartedEvent); return -__LINE__; }
建立執行緒
將事件作為引數傳入執行緒
// create arguments for loopback capture thread LoopbackCaptureThreadFunctionArguments threadArgs; threadArgs.hr = E_UNEXPECTED; // thread will overwrite this threadArgs.pMMDevice = prefs.m_pMMDevice; threadArgs.bInt16 = prefs.m_bInt16; threadArgs.hStartedEvent = hStartedEvent; //將這兩個事件作為引數,傳入執行緒 threadArgs.hStopEvent = hStopEvent; // threadArgs.nFrames = 0; threadArgs.bMono = prefs.m_bMono; threadArgs.iSampleRateDivisor = prefs.m_iSampleRateDivisor;
//建立執行緒
HANDLE hThread = CreateThread(
NULL, 0,
LoopbackCaptureThreadFunction, &threadArgs,
0, NULL
);
if (NULL == hThread) {
printf("CreateThread failed: last error is %u\n", GetLastError());
CloseHandle(hStopEvent);
CloseHandle(hStartedEvent);
return -__LINE__;
}
執行緒內部處理:預處理過程、無限迴圈過程
hr = pAudioClient->Start();
if (FAILED(hr)) {
printf("IAudioClient::Start failed: hr = 0x%08x\n", hr);
AvRevertMmThreadCharacteristics(hTask);
pAudioCaptureClient->Release();
CloseHandle(hWakeUp);
pAudioClient->Release();
return hr;
}
//預處理結束,通知主執行緒,此時主執行緒使用WaitForMultipleObjects 等待
SetEvent(hStartedEvent);
// loopback capture loop
HANDLE waitArray[2] = { hStopEvent, hWakeUp };
DWORD dwWaitResult;
//迴圈階段
bool bDone = false;
for (UINT32 nPasses = 0; !bDone; nPasses++)
主執行緒通過WaitForMultipleObjects,獲知執行緒是在預處理階段失敗,還是已經進入迴圈階段
DWORD WaitForMultipleObjects(
DWORD nCount, // 控制代碼的數量 最大值為MAXIMUM_WAIT_OBJECTS(64)
CONST HANDLE* lpHandles, //控制代碼陣列的指標
BOOL fWaitAll, //等待所有事件有訊號,還是隻要一個有訊號就返回
DWORD dwMilliseconds //超時時間 超時後向執行。 如果為INFINITE 永不超時。如果沒有訊號量就會在這死等。
);
This function returns a value when either any one of the specified objects is in the signaled state, or the time-out interval elapses.
當WaitForMultipleObjects()等到多個核心物件的時候,
如果它的bWaitAll 引數設定為false
其返回值
等於WAIT_OBJECT_0 + lpHandles陣列的序號(從0開始計數)
如果,多個都有核心被同時觸發,有訊號,則返回其中序號最小的那個。
判斷:主執行緒 判斷 子執行緒 是否預處理成功
//等待事件開始,或者執行緒結束
// wait for either capture to start or the thread to end
HANDLE waitArray[2] = { hStartedEvent, hThread };
DWORD dwWaitResult;
dwWaitResult = WaitForMultipleObjects(
ARRAYSIZE(waitArray), waitArray,
FALSE, INFINITE
);
//執行緒結束了,但此時hStartedEvent還沒有訊號,說明執行緒在初始化階段 失敗了
if (WAIT_OBJECT_0 + 1 == dwWaitResult) {
printf("Thread aborted before starting to loopback capture: hr = 0x%08x\n", threadArgs.hr);
CloseHandle(hStartedEvent);
CloseHandle(hThread);
CloseHandle(hStopEvent);
return -__LINE__;
}
//未預期的錯誤
if (WAIT_OBJECT_0 != dwWaitResult) {
printf("Unexpected WaitForMultipleObjects return value %u", dwWaitResult);
CloseHandle(hStartedEvent);
CloseHandle(hThread);
CloseHandle(hStopEvent);
return -__LINE__;
}
//執行緒初始化成功,關閉開始事件,執行緒執行無限迴圈階段
CloseHandle(hStartedEvent);
結束:主執行緒結束子執行緒
將結束事件設定為有訊號
SetEvent(hStopEvent);
子執行緒在迴圈過程中,要判斷結束事件是否有訊號,有則結束
HANDLE waitArray[2] = { hStopEvent, hWakeUp };
//子執行緒在迴圈過程中判斷
dwWaitResult = WaitForMultipleObjects(
ARRAYSIZE(waitArray), waitArray,
FALSE, INFINITE
);
//主執行緒將結束事件設定為有訊號,子執行緒迴圈過程中判斷 若有訊號,則結束迴圈
if (WAIT_OBJECT_0 == dwWaitResult) {
printf("Received stop event after %u passes and %u frames\n", nPasses, *pnFrames);
bDone = true;
continue; // exits loop
}