1. 程式人生 > >c++ 知識點 : 執行緒相關

c++ 知識點 : 執行緒相關

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
        }