トップページ > 過去ログ > 記事閲覧
NowLoading画面
名前:KA 日時: 2010/01/10 21:34

NowLoading画面を表示するのにスレッドを作って実行してみたのですが、途中で停止してしまいました。 停止させずにするにはどうすればよいでしょうか? //ソースコード #include <DxLib.h> #include <windows.h> #include <process.h> bool Loading_End = FALSE; int ProcessLoop() { if(ProcessMessage()) return -1; if(ClearDrawScreen()) return -1; if(CheckHitKey(KEY_INPUT_ESCAPE)) return -1; return 0; } unsigned int WINAPI NowLoading(void* pParameter) { //NowLoading用画像読み込み while(ProcessLoop()) {         //画像表示 if(Loading_End) break; ScreenFlip(); } return 0; } int WINAPI WinMain(...) { SetAlwaysRunFlag(TRUE); SetOutApplicationLogValidFlag(FALSE); if(DxLib_Init()!=0||SetDrawScreen(DX_SCREEN_BACK)!=0) return -1; unsigned int thID; HANDLE hTh= (HANDLE)_beginthreadex(NULL, 0, NowLoading, NULL, 0, &thID); //メイン関数用画像読み込み Loading_End = TRUE; CloseHandle(hTh); while(ProcessLoop()==0) { //ゲームメイン処理 } DxLib_End(); return 0; }

Page: 1 |

Re: NowLoading画面 ( No.1 )
名前:いっち 日時:2010/01/10 21:59

NowLoading関数の > while(ProcessLoop()) は while( ProcessLoop() == 0 ) が、正しいのではないでしょうか?
Re: NowLoading画面 ( No.2 )
名前:KA 日時:2010/01/10 22:13

それは失敗していじった後のコーディングミスです。すみません。 今、直してもう一回実行しました。 まだ最初なのでメイン関数用画像読み込みの後にWaitTimer関数で時間を止めていたのですが、 何故かその時間を延ばし、コーディングミスを直すと一回だけうまくいったのですが、二回目以降は停止してしまいます。
Re: NowLoading画面 ( No.3 )
名前:いっち 日時:2010/01/10 23:02

> CloseHandle(hTh); の前に以下の文を入れてみてください。 WaitForSingleObject( hTh, INFINITE ); 終了フラグをセットした後、スレッドが終了する前にCloseHandleされている可能性があります。 それと、無くても平気だと思いますがNowLoading関数のreturn分の前で、 _endthreadex関数を呼んでほうが良いかも知れません。
Re: NowLoading画面 ( No.4 )
名前:KA 日時:2010/01/10 23:18

コードを変更した後、一度はうまくいったのですが、次に起動してみるとやっぱりだめでした。 デバックモードで実行してみると、二回目はこんなエラーが出て止まります。 Windows によって Debug.exe でブレークポイントが発生しました。 ヒープが壊れていることが原因として考えられます。Debug.exe または読み込まれた DLL にバグがあります。 あるいは、Debug.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。 可能であれば、出力ウィンドウに詳細な診断情報が表示されます。 ウィンドウを閉じるボタンで閉じているのですが関係あるでしょうか?
Re: NowLoading画面 ( No.5 )
名前:いっち 日時:2010/01/11 00:23

私の環境では問題なく動作しているように見受けられます。 以下のコードでも同様の現象が出ますでしょうか? "test1.bmp"はDxLibのサンプルに同梱されているものです。 また、WaitTimerの値がわからないのでとりあえず10000が設定されています。 #include <windows.h> #include <process.h> #include "DxLib.h" bool quit_thread; int test; int graph_handle; unsigned int __stdcall MyThread( void *p ) { while( ProcessMessage( ) == 0 ) { ClearDrawScreen( ); DrawGraph( 0, 0, graph_handle, TRUE ); DrawFormatString( 0, 0, GetColor( 255, 255, 255 ), "In Thread Test = %d", test ); ScreenFlip( ); if ( quit_thread == true ) { if ( test-- ) continue; break; } test++; } _endthreadex( 0 ); return 0; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); if ( DxLib_Init( ) < 0 ) return -1; SetDrawScreen( DX_SCREEN_BACK ); graph_handle = LoadGraph( "test1.bmp" ); quit_thread = false; unsigned int thread_id; HANDLE thread_handle = (HANDLE)_beginthreadex( NULL, 0, &MyThread, NULL, 0, &thread_id ); WaitTimer( 10000 ); quit_thread = true; WaitForSingleObject( thread_handle, INFINITE ); CloseHandle( thread_handle ); test = 0; while( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && test < 500 ) { test++; ClearDrawScreen( ); DrawFormatString( 0, 0, GetColor( 255, 255, 255 ), "Out of Thread %d", test ); ScreenFlip( ); } DeleteGraph( graph_handle ); DxLib_End(); return 0; }
Re: NowLoading画面 ( No.6 )
名前:KA 日時:2010/01/11 11:49

実行してみましたら、うまくいきました。 また、ProcessLoop関数などを組み込んでみてもうまくいきました。 そして自分のソースに組み込んでみましたがやっぱり、一回目は成功し、二回目からは失敗しました。 どうもわかりませんが、実行するごとにエラー内容が変わります。時々成功するときもあります。
Re: NowLoading画面 ( No.7 )
名前:いっち 日時:2010/01/11 19:23

今までにお見せ頂いたソースで原因を判断するのは少し難しいようです。 もし、問題ないようでしたら、事象の発生するソースをアップローダに上げて頂けますでしょうか? ちなみに、ご使用中のDxLibのバージョンは3.01でしょうか?
Re: NowLoading画面 ( No.8 )
名前:KA 日時:2010/01/12 20:47

ソースコード上げました。 ttp://www1.axfc.net/uploader/Sc/so/72965 キーは「Now」です。 画像は都合上同梱していないので、コメントアウトしています。 エラーは同様ですが何故か確率が下がっていたりします。コメントアウトをはずすと上がるかもしれません。 また、DxLibのバージョンは3.01でした。
Re: NowLoading画面 ( No.9 )
名前:いっち 日時:2010/01/12 23:16

何度か実行してみましたが、プログラムが停止すると言った事象は出ませんでした。 しかし、Load画面が真っ暗になることがありました。 (画像は1024*768のベタ塗りpngを自前で表示させて使ってます。) DxLib.hの中に気になる関数があったので使ってみました。 DxLib_Init関数を実行する前に下記の記述を入れてみてください。 > SetMultiThreadFlag( TRUE ); この関数にどのような効果があるのかわからないのですが、 とりあえず、Load画面が真っ暗になるようなことは無くなりました。 もしかしたら、事象を解決してくれるかもしれません・・・。 (追記) SetMultiThreadFlagをFALSEにして何度か実行してみるとDxlibの不特定の関数でアクセス違反が発生していました。 SetMultiThreadFlagはやはり必要なようです。何らかのペナルティがあるかもしれないので(そんな感じはありませんでしたが)、 マルチスレッドを明らかに行っていない部分ではFALSEにしておいたほうが良いかも知れません。
Re: NowLoading画面 ( No.10 )
名前:KA 日時:2010/01/13 21:17

SetMultiThreadFlag関数を使ってみたところ、20回ほど起動した中で、1回エラーが出るか出ないか程度になりました。 確かに、デバックすると不特定の関数でエラーが出ていたんですよね… この関数を有効にするとよさそうです。 本当にありがとうございました。
Re: NowLoading画面 ( No.11 )
名前:いっち 日時:2010/01/13 21:55

現在スレッドの中で行っているNowLoading用の画像のロードをスレッドの外に出すことでより安定すると思います。 (おそらくLoadGraphのなかで競合が起きているので) ハンドルを大域変数かアドレスで渡すようにしてみてください。
Re: NowLoading画面 ( No.12 )
名前:いっち 日時:2010/01/13 22:57

この事象はDxLibのバグというより現時点での制限だと思いますが、 一応、再現用のソースを作ってみました。 SetMultiThreadFlagをしていますが、2つのスレッドで 延々とLoadGraphを繰り返すと言う無茶をしているので落ちます #include <process.h> #include "DxLib.h" bool quit_thread; const char *file1 = "test1.bmp"; const char *file2 = "test2.bmp"; unsigned int WINAPI MyThread( void *p ) { int handle; while( 1 ) { handle = LoadGraph( (const char *)p ); if ( quit_thread == true ) break; DeleteGraph( handle ); } _endthreadex( 0 ); return 0; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); SetMultiThreadFlag(TRUE); if ( DxLib_Init( ) < 0 ) return -1; quit_thread = false; unsigned int thread_id1; unsigned int thread_id2; HANDLE thread_handle1 = (HANDLE)_beginthreadex( NULL, 0, &MyThread, (void*)file1, 0, &thread_id1 ); HANDLE thread_handle2 = (HANDLE)_beginthreadex( NULL, 0, &MyThread, (void*)file2, 0, &thread_id2 ); while( ProcessMessage( ) == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { } quit_thread = true; WaitForSingleObject( thread_handle1, INFINITE ); CloseHandle( thread_handle1 ); WaitForSingleObject( thread_handle2, INFINITE ); CloseHandle( thread_handle2 ); DxLib_End( ); return 0; }

Page: 1 |