Windows(Native)におけるスレッド処理 - inoueshinichi/Wiki_Windows GitHub Wiki
参考(公式)
参考
WaitSigleObjectが待機できるハンドル(プロセスで一意なオブジェクト)一覧
- 変更通知
- コンソール入力
- イベント
- メモリ リソース通知
- Mutex
- Process
- Semaphore
- スレッド
- 待機可能タイマー
スレッドにイベントループを実装する場合, メッセージキューの作成を待ってから実行する
- ウィンドウを直接的/間接的に生成する際に使用する待機関数は,
WaitSingleObject
ではなくMsgWaitForMultiObjects
またはMsgWaitForMultiObjectsEx
を使用すること.
- 直接または間接的にウィンドウを作成する待機関数とコードを呼び出す場合は注意が必要.
- スレッドがウィンドウを作成する場合は, メッセージを処理する必要がある(イベントループ).
- メッセージブロードキャストは, システム内のすべてのウィンドウに送信される.
- タイムアウト間隔のない待機関数を使用するスレッドでは, システムがデッドロックする可能性がある.
// ワーカースレッド関数
unsigned int WINAPI WorkerThreadFunc(void *arg)
{
HANDLE hThreadInitEvent = (HANDLE)arg;
MSG uMsg;
// スレッドキューの作成
PeekMessage(&uMsg, NULL, 0, 0, PM_NOREMOVE);
// イベント(False -> True)
::SetEvent(hThreadInitEvent);
while (true)
{
if (PeekMessage(&uMsg, NULL, 0, 0, PM_NOREMOVE) > 0)
{
if (GetMessage(&uMsg, NULL, 0, 0) > 0)
{
~
}
else
{
break; // WM_QUIT
}
}
}
::_endthreadex(1234);
return 0;
}
// メインスレッド側
int main()
{
HANDLE hThreadInitEvent = ::CreateEvent(NULL, // SECURITY_ATTRIBUTE構造体
TRUE, // リセットのタイプ(True:自動, False:手動)
FALSE, // 初期状態(True:シグナル状態, False:非シグナル状態)
NULL);
// ワーカースレッド作成
DWORD nThreadId = 0;
HANDLE hThread = (HANDLE)::_beginthreadex(NULL, // SECURITY_ATTRIBUTE構造体
0, // スタックサイズ(0は呼び出し側と同じサイズ)
&WorkerThreadFunc, // ワーカスレット関数ポインタ
(void*)hThreadInitEvent, // スレッド関数の引数
0, // 作成オプション (0: CREATE_SUSPENDED)
&nThreadId // スレッドID (DWORD)
);
// スレッドキューの作成待ち
//::WaitForSingleObject(hThreadInitEvent, INFINIT); // 恐らくこの`WaitForSingleObject`はアンチパターン
MsgWaitForMultiObjects(~~~); // こっちを使う?
// スレッド初期化イベントの破棄
::CloseEvent(hThreadInitEvent);
// ワーカースレッドへのメッセージの送信
PostThreadMessage(nThreadId, ~);
// ~~~~
// スレッド終了待ち
::WaitForSingleObject(hThread, INFINIT);
// スレッドイベントの破棄
::CloseEvent(hThread);
// ワーカースレッドの終了状態を取得
DWORD dwExitCode;
::GetExitCodeThread(hThread, &dwExitCode);
}