Win32執行緒——等待另一個執行緒結束
轉載:
https://blog.csdn.net/yss28/article/details/53646627
《Win32多執行緒程式設計》–Jim Beveridge & Robert Wiener
“等待某個什麼東西”是執行緒常常需要做的事。等待是執行緒的“必要之惡”。
如果你沒有等待執行緒結束就莽撞地結束程式,執行緒會被系統強制結束掉——在它完成它的工作之前。
由於讓執行緒停工是作業系統的責任,很合理地我們會認為作業系統也有責任讓其他執行緒知道某個執行緒停工了。
Sleep()
這個函式要求作業系統中止執行緒動作,直到渡過某個指定時間之後才恢復。
#include <stdio.h>
#include <Windows.h>
DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
}
int main(void) {
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
Sleep(?); // 不可能事先知道要等待Thread多久
CloseHandle(hThread);
return 0;
}
GetExitCodeThread()輪詢檢查
使用 GetExitCodeThread() 可以決定一個執行緒是否還在執行。
#include <stdio.h>
#include <Windows.h>
DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
}
int main(void) {
DWORD exitCode = 0;
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
while (1) {
GetExitCodeThread(hThread, &exitCode); // 嚴重浪費 CPU 時間
if (STILL_ACTIVE != exitCode)
break;
}
CloseHandle(hThread);
return 0;
}
WaitForSingleObject()
可看成一個新版的 Sleep() ,它能夠在某個執行緒結束時(而不是某段時間結束時)被呼叫。
可使用的核心物件有兩種狀態:激發與未激發。WaitForSingleObject() 會在目標物變成激發狀態時返回。
物件 | 說明 |
---|---|
Thread(執行緒) | 當執行緒結束時,執行緒物件即被激發。當執行緒還在進行時,則物件處於未激發狀態。 |
Process(程式) | 當程式結束時,程式物件即被激發。當程式還在進行時,則物件處於未激發狀態。 |
Event | Event 物件的狀態直接受控於應用程式所使用的三個Win32函式:SetEvent()、PulseEvent()、ResetEvent()。CreateEvent()和OpenEvent()都可以傳回一個event object handle。Event物件的狀態也可以被作業系統設定。 |
Mutex | 如果mutex沒有被任何執行緒擁有,它就是處於激發狀態。一旦一個等待mutex的函式返回了,mutex也就自動重置為未激發狀態。 |
Semaphore | Semaphore有點像mutex,但它有個計數器,可以約束其擁有者(執行緒)的個數。當計數器內容大於 0時,semaphore處於激發狀態,當計數器內容等於0時,semaphore處於未激發狀態。 |
#include <stdio.h>
#include <Windows.h>
DWORD WINAPI Thread(void *arg) {
// doing something
return 0;
}
int main(void) {
HANDLE hThread = CreateThread(NULL, 0, Thread, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE); // 等待,直到執行緒被激發
CloseHandle(hThread);
return 0;
}
WaitForMultipleObjects()
允許你在同一時間等待一個以上的物件。你必須將一個由 handles 組成的陣列交給此函式,並指定要等待其中一個物件或是全部的物件。
(範例:保持執行緒池中始終有3個執行緒在執行)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define POOL_SIZE 3 // 執行緒池大小
#define TASK_NUM 6
DWORD WINAPI ThreadFunc(LPVOID n) {
srand(GetTickCount());
Sleep(rand()%5000+500);
printf("%d over\n", n);
return ((DWORD)n);
}
int main(void){
HANDLE hThrds[POOL_SIZE];
int pIdx = 0, tIdx;
DWORD rc;
for (tIdx = 1; tIdx <= TASK_NUM; tIdx++) {
if (tIdx > POOL_SIZE) {
rc = WaitForMultipleObjects(POOL_SIZE, hThrds, FALSE, INFINITE); // 等待hThrds陣列中任意一個變為激發狀態,返回其索引
pIdx = rc - WAIT_OBJECT_0;
assert(pIdx >= 0 && pIdx < POOL_SIZE);
printf("%d terminated\n", pIdx);
CloseHandle(hThrds[pIdx]);
}
hThrds[pIdx++] = CreateThread(NULL, 0, ThreadFunc, (LPVOID)pIdx, 0, NULL);
printf("Thread #%d launched (pIdx %d)\n", tIdx, pIdx);
}
WaitForMultipleObjects(POOL_SIZE, hThrds, TRUE, INFINITE); // 等待hThrds陣列中所有執行緒變為激發狀態
for (pIdx = 0; pIdx < POOL_SIZE; pIdx++)
CloseHandle(hThrds[pIdx]);
return EXIT_SUCCESS;
}
結果:
GUI 程式中等待
Windows 程式中的“主訊息迴圈”看起來像這個樣子:
while (GetMessage(&msg, NULL, 0, 0,))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage() 有點像是特殊版本的 WaitForSingleObject(),它等待訊息而
不是核心物件。一旦你呼叫 GetMessage() ,除非有一個訊息真正進入你的訊息
佇列( message queue )之中,否則它不會返回。
如果你在主執行緒中正使用 WaitForSingleO bject()或 WaitForMultipleObjects()等待某個物件被激發,你根本沒有辦法回到主訊息迴圈中去。
為了解決這個問題,主訊息迴圈必須修改,使它得以同時等待訊息或是核心物件被激發。你必須使用一個 MsgWaitForMultipleObjects() 函式。這個函式非常類似WaitForMultipleObjects(),但它會在“物件被激發”或“訊息到達佇列”時被喚醒而返回。MsgWaitForMultipleObjects() 多接受一個引數,允許指定哪些訊息是觀察物件。
相關文章
- Windows10 VS2017 C++多執行緒傳參和等待執行緒結束WindowsC++執行緒
- Rust 程式設計影片教程(進階)——016_2 建立執行緒與等待執行緒結束Rust程式設計執行緒
- Rust 程式設計視訊教程(進階)——016_2 建立執行緒與等待執行緒結束Rust程式設計執行緒
- Java CompletableFuture:allOf等待所有非同步執行緒任務結束Java非同步執行緒
- 模擬主執行緒等待子執行緒的過程執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- Java 多執行緒基礎(六)執行緒等待與喚醒Java執行緒
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 執行緒和執行緒池執行緒
- 多執行緒--執行緒管理執行緒
- 執行緒與多執行緒執行緒
- 執行緒 執行緒池 Task執行緒
- 多執行緒【執行緒池】執行緒
- [Java併發]執行緒的並行等待Java執行緒並行
- 多執行緒:執行緒池理解和使用總結執行緒
- 深入淺出Win32多執行緒程式設計--之MFC的多執行緒Win32執行緒程式設計
- 保證執行緒在主執行緒執行執行緒
- Thread 中的 join() 方法的作用是呼叫執行緒等待該執行緒執行完後,再繼續執行thread執行緒
- Java多執行緒-執行緒中止Java執行緒
- 多執行緒之初識執行緒執行緒
- 執行緒控制之休眠執行緒執行緒
- 多執行緒,到底該設定多少個執行緒?執行緒
- Java之 join 等待執行緒終止Java執行緒
- 多執行緒之等待通知機制執行緒
- 主執行緒等待所有其他執行緒執行完畢,然後再繼續執行主執行緒的邏輯,有以下幾種方法可以實現:執行緒
- 執行緒、開啟執行緒的兩種方式、執行緒下的Join方法、守護執行緒執行緒
- java執行緒之守護執行緒和使用者執行緒Java執行緒
- 執行緒(一)——執行緒,執行緒池,Task概念+程式碼實踐執行緒
- 多執行緒系列之 執行緒安全執行緒
- 二. 執行緒管理之執行緒池執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- Java多執行緒之執行緒中止Java執行緒
- Android多執行緒之執行緒池Android執行緒
- Java多執行緒-執行緒狀態Java執行緒
- Java多執行緒-執行緒通訊Java執行緒
- kuangshenshuo-多執行緒-執行緒池執行緒
- java 多執行緒守護執行緒Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒