- ベストアンサー
マルチスレッドについての質問
- マルチスレッドについての質問をしましたが、ロードしていない部分がありました。
- スレッドの中身を詳細に説明します。
- 質問に対してのご助力をお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
提示されたソースだけみると、メイン側はスレッド動作中スレッドの終了待ちをしているだけで、何もしてないですね。GInit()をメインから呼ぶのと変わらないように見えます。 スレッド関数は、静的に割りつける必要があるので、クラス内に関数を配置する場合static が必要です。this ポインタ渡しをしているので大丈夫かと思いますが。ヘッダでstatic宣言してる? static unsigned int WINAPI GameMain::loadthread(void *lpx) スレッドの待ち方がいまいちです。 通常、スレッド間の同期処理はイベントを使用します。今回のはロード専用スレッドであれば、スレッドの終了待ちです。 hThread = _beginthreadex() WaitForSingleObject(hThread) とか。 スレッドの待ち方は、メイン側でその時に何をしているかによって変わってきます。メッセージループを回しておきたいのであれば、スレッド終了待ちはご法度ですし。
その他の回答 (4)
- salsberry
- ベストアンサー率69% (495/711)
No.1&No.3です。 No.3で「No.1さんが書いているとおり」と書いたのは「No.2さんが書いているとおり」の誤りです。
- gentoo314
- ベストアンサー率41% (15/36)
空ループでワークスレッドの終了待ちをするのはやめましょう。 スレッド間で同期処理をするときは、必ず WaitForSingleObject() か、WaitForMultipleObjects()で待ちます。 ワークスレッドの処理状況をメインスレッドに通知するときにイベントを使用します。以下サンプルです。 main() { hEvent = CreateEvent(); hThread = _beginthreadex(); const HANDLE handles[2] = { hThread, hEvent }; while(1){ ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE); switch(ret){ case WAIT_OBJECT_0: // スレッド終了時の処理 CloseHandle(hThread); ... goto end; case WAIT_OBJECT_1: // ロード中の画面描画処理 // load_item の値に応じた画面表示 break; default: // エラー処理 } end: } thread() { //処理1 load_item++ SetEvent(hEvent); // メインスレッドに通知 //処理2 load_item++ SetEvent(hEvent); // メインスレッドに通知 } メインスレッドで実行するGameMain::LoadScreen()この関数ですが、もしかしてメッセージハンドラ内からコールされます ? そうであれば、今回のサンプルはだめです。イベントの代わりに、PostMessage() でメッセージをメインスレッドのメッセージループに通知します。
- salsberry
- ベストアンサー率69% (495/711)
なるほど、graphloaded_flgがTRUEになった後もセカンダリスレッド側ではまだ処理が続くんですか。 前の質問への回答で「プライマリスレッドでgraphloaded_flg!=TRUEのときに100ミリ秒くらいスリープしたらどうなりますか?」と書きましたが、それは撤回します。graphloaded_flgの値に関係なく、while (loopflg) { ~ } の中で毎回スリープさせてみてください。 ただし、それで動くようになったとしても、それは「ビジーループのせいで意図したとおりに動いていなかった」ことの確認でしかなく、正しい解決法とは限りません。No.1さんが書いているとおり、適切なイベントを使って同期処理をするべきでしょう。 あともう一つ、プライマリスレッドではload_itemの値を書き換えていないのにわざわざクリティカルセクションに入っているのはなぜでしょうか。
- salsberry
- ベストアンサー率69% (495/711)
質問番号5774406の続きですね。 GameMain::loadthread()が呼んでいるgm->GInit()の内容が分からないので、誰も何も答えられないと思いますよ。 また「ロードしていない部分がありました」についても、プログラムのどこでどうなると思っていたのに実際にはどうなってしまったのかを具体的に説明してください。
お礼
たびたびのご返答ありがとうございます。 ロードしていないのはサウンドです。 GInitの関数の中身の縮小版を載せておきますのでよろしければ返答をお願いします。 HRESULT GameMain::GInit() { //インスタンス生成 ここでインスタンスの生成をしております。 //2D画像のロード 2D画像のロード関数 // アクセスの競合を回避するために、クリティカルセクションを所有してデータメンバを操作する EnterCriticalSection( &m_criticalSection ); ++load_item; graphloaded_flg=TRUE; LeaveCriticalSection( &m_criticalSection ); //ムービーのロード ムービーロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //サウンドのロード サウンドロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //キャラのロード マイキャラロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //敵キャラのロード 敵キャラロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //ボスキャラのロード ボスキャラロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //フィールドのロード フィールドロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //エフェクトのロード エフェクトロード関数 EnterCriticalSection( &m_criticalSection ); ++load_item; LeaveCriticalSection( &m_criticalSection ); //環境設定 //平行光源設定 m_view->ParallelLight(PARALLEL_RED, PARALLEL_GREEN, PARALLEL_BLUE); //環境光の設定 m_view->AmbientLight(AMBIENT_RED, AMBIENT_GREEN, AMBIENT_BLUE, AMBIENT_ALPHA); //射影変換 m_view->ProjConversion(); return S_OK; }
お礼
ご指摘ありがとうございます。 loadthreadのほうはstaticにしてはおります。 スレッドの待ち方というのも一応CheckThreadという関数を作っております。 CheckThreadについて下記にソースを載せておきます。 int GameMain::CheckThread(const HANDLE &a_threadHandle) { // ---------------------------------------- // スレッドの状態を確認する // ---------------------------------------- GetExitCodeThread( a_threadHandle, &dwExCode ); // スレッドは動作中 if ( dwExCode == STILL_ACTIVE ) { return THREAD_RUNNING; } else { // スレッドが終了する(シグナル状態になる)まで待機 DWORD threadCondition = WaitForSingleObject( a_threadHandle, INFINITE ); // スレッドがシグナル状態ならば、スレッドのハンドルを閉じる if ( threadCondition == WAIT_OBJECT_0 ) { // スレッドのハンドルを閉じる if ( FAILED( CloseHandle( a_threadHandle ) ) ) { // ハンドルを閉じられなかった場合はエラーを返す return THREAD_ERROR; } return THREAD_EXIT; } } return THREAD_RUNNING; }