この記事は2020年04月20日に投稿しました。
目次
1. はじめに
こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回はWin32 APIでスレッドを使用する方法(その2)についてです。
2. Win32 APIでスレッドを使用する(その2)
Win32 APIでスレッドを使用する方法(その2)ですが、スレッドを作成時に起動せず後で起動する方法です。
スレッドを作成時に起動せず後で起動する方法ですが、以下のような手順になります。
- CreateThreadでスレッドを作成する際、第5引数dwCreationFlagsに"CREATE_SUSPENDED"を指定します。
- スレッド作成後、スレッドを起動したいタイミングでResumeThread関数を呼び出し、スレッドを起動します。
CreateThread関数
書式
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, __drv_aliasesMem LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
引数
lpThreadAttributes
返されたハンドルを子プロセスが継承できるかどうかを決定するSECURITY_ATTRIBUTES構造体へのポインター。
NULLの場合、ハンドルを継承することはできません。
dwStackSize
スタックの初期サイズ(バイト単位)
この値は最も近いページに丸められます。
このパラメーターがゼロの場合、新しいスレッドは実行可能ファイルのデフォルトサイズを使用します。
lpStartAddress
スレッドによって実行される関数へのポインター。
スレッドによって実行される関数は、以下のThreadProc関数で定義される書式である必要があります。
(関数名は任意です)
lpPrameter
スレッドに渡される変数へのポインター
dwCreationFlags
スレッドの作成を制御するフラグ
定数 | 値 | 内容 |
---|---|---|
- | 0 | スレッドは作成直後に実行されます。 |
CREATE_SUSPENDED | 0x00000004 | スレッドは中断状態で作成され、ResumeThread関数が呼び出されるまで実行されません 。 |
STACK_SIZE_PARAM_IS_A_RESERVATION | 0x00010000 | dwStackSizeのパラメータは、スタックの最初の予約サイズを指定します。 このフラグが指定されていない場合、dwStackSizeはコミットサイズを指定します。 |
lpThreadId
スレッド識別子を受け取る変数へのポインター。
このパラメーターが NULLの場合、スレッドIDは返されません。
戻り値
関数が成功した場合、新しいスレッドへのハンドル
関数が失敗した場合、NULL
拡張エラー情報を取得するには、GetLastError関数を呼び出します 。
ThreadProc関数
※関数名は任意です。
書式
DWORD WINAPI ThreadProc( _In_ LPVOID lpParameter );
引数
lpParameter
CreateThread関数のlpParameterパラメーターで渡される変数へのポインタ
戻り値
関数の成功またはエラーを示す値
ResumeThread関数
※関数名は任意です。
書式
DWORD ResumeThread( HANDLE hThread );
引数
hThread
スレッドへのポインタ
戻り値
関数が成功した場合、戻り値はスレッドの以前の中断カウント
関数が失敗した場合、戻り値は(DWORD)-1
拡張エラー情報を取得するには、GetLastError関数を呼び出します。
実装例
#include <iostream> #include <Windows.h> #include <random> // スレッドで動作する関数 DWORD WINAPI ThreadProc(LPVOID pParam) { std::random_device rnd; for (int i = 0; i < 100; ++i) { std::cout << std::hex << rnd() << std::endl; } return 0; } int main() { // スレッドを停止した状態で生成します。 std::cout << "スレッドを生成します。" << std::endl; HANDLE hThread = CreateThread( NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, NULL ); // スレッドを起動する前の処理 // ここでは単純にスリープします。 Sleep(3000); // スレッドを起動します。 std::cout << "スレッドを開始します。" << std::endl; ResumeThread(hThread); // スレッドの終了を待ちます。 WaitForSingleObject(hThread, INFINITE); std::cout << "スレッドが終了しました。" << std::endl; // スレッドハンドルを閉じます。 CloseHandle(hThread); getchar(); return 0; }
API Reference
3. おわりに
前回
はスレッドを生成すると同時にスレッドも起動していました。
今回スレッドをあとから起動する方法を知ったので、その方法を紹介しました。
紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。
私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリやウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。
また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。
EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688