• ベストアンサー

マルチスレッドプログラミングについて

マルチスレッドプログラミングについていくつか教えて下さい。 マルチスレッドの基礎がまだ分かってないので初心者でも分かり易いようにお願いします。 1:イベントオブジェクトについて教えて下さい。 「イベントオブジェクト」の概念がよく分かりません。 ○シグナル状態と非シグナル状態とはどういう状態なのでしょうか? ○自動リセットの場合ではどのタイミングで切り替わっているのでしょうか?(下記のソースの場合) ○手動リセットの場合ではどのタイミングで切り替えればよいのでしょうか?(下記のソースの場合) 2:CloseHandle() と ExitThread() について教えて下さい。 ○この2つの関数の役割の違いについて教えて下さい。 「スレッドハンドルを閉じる=スレッドを終了」ではないのでしょうか? また、これらの関数実行時にシグナル状態は気にする必要はありますか?(シグナル状態にしなくてよいのか?) 下記のソースは簡略化のためかなり省略されています。 DWORD WINAPI ThreadProc( DWORD i ) { while( true ) { DWORD r = WaitForMultipleObjects( 2, hEvent, FALSE, INFINITE ); if( r == WAIT_OBJECT_0 ) { // 処理1 } else if( r == WAIT_OBJECT_0 ) { // 処理2 } else { ExitThread( TRUE ); // スレッド終了 } } } void MainProc() { // 自動リセットのイベントオブジェクト作成 for( int i=0; i<2; i++ ) { hEvent[i] = CreateEvent( NULL, FALSE, FALSE, NULL ); } // スレッドを作成 hThread = CreateThread( NULL, 0, ThreadProc, NULL, 0, &dwThreadID ); }

質問者が選んだベストアンサー

  • ベストアンサー
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.2

>・自動リセットは自動でシグナルと非シグナルを切り替えてくれるものだと思っていたのですが、間違っているのでしょうか? 違います。シグナルを受け取った時に自動的にリセットする(非シグナルに切り替える)だけで、勝手にシグナル状態にはしません。 >初期状態が非シグナルなのでこのまま変化しないということはスレッドはずっと動かないということですか? そのはずです。 >シグナル状態になったときに制御を返すとありますが、シグナル状態ではなく非シグナル状態になるのですか? シグナル状態になったから制御を返しますが,返すときにリセット動作する(非シグナル状態にする)だけです。 自動リセットを使う場合は、WaitObjedtて止まっているスレッドを動かすことにあるので、動いてしまえば非シグナル状態にしても問題ありません。 >初期状態に非シグナルを指定していてもちゃんと返ってきます 多分エラーで戻っているのでは。イベント作ったプロセス終了しているように見えますが、問題ないですか? INFINITEが指定されているのでシグナル状態になるまで戻ってこないはずです。 時間が設定してあれば、タイムアウトで戻ってきますけど。 通常勝手にSetEventが呼ばれることは無いと思います。 >スレッドを使わなくなったときはどっちを使うべきでしょうか? ExitThread() CreateThread()についてもう一度読んでください。 これに限らず、たいていマニュアルにあると思いますが。 ちなみに、古いWIN32APIのHELP読んだだけで回答してますので、自信無しです。 他のOSでは似たことやってますし、Windowsでもイベントでなくメッセージでプロセス間WaitForMultipleObjectsは使ったことありますが。

mainuser
質問者

お礼

やっと分かってきました。 丁寧に教えていただきありがとうございました。

その他の回答 (2)

noname#30727
noname#30727
回答No.3

なんらかの同期オブジェクト(例えばイベント)がシグナル状態・非シグナル状態のどちらであっても、スレッドが勝手にサスペンドすることはありません。 同期オブジェクトがシグナル状態であれば、その同期オブジェクトを指定してWaitFor???()を呼び出せば、すぐに戻ってきます。非シグナル状態であれば、シグナル状態になるか、タイムアウトするまで、WaitFor???()から戻ってきません。(呼び出したスレッドはサスペンド状態になり、その間CPU時間は割り当てられない) 自動リセットイベントは、初期状態をリセット状態であるようにします。このイベントを待つ必要があれば、WaitFor???()を呼び出します。別のスレッドが、このイベントをセットすることで、このイベントを待っていたスレッドがWaitFor???()から戻ります(=サスペンドが解除される)。再度このイベントを待つ前に誰かがイベントをリセットしてやらないとイベントの意味が無くなってしまうのですが、このイベントを待っていたスレッドを通過させると同時にイベントもリセットさせるのが自動リセットイベントです。 待つ→セット→待つ→セットの繰り返しだけで同期が取れるようになっています。 シグナル状態=青信号、非シグナル状態=赤信号、信号を見て止まるかどうかは、WaitFor???()の呼び出しと理解するといいでしょう。止まっているものを動かすには、別の誰かが信号を青にしてやる必要があります。 スレッドハンドルは、スレッドの生存状態と同期を取る為にも使用されるので、ExitThread()やTerminateThread()によってスレッドが終了しても、スレッドハンドルは有効です。スレッドハンドルはスレッドそのものでは無いので、スレッドハンドルをクローズしても、スレッドは終了しません。 スレッドが終了しているかどうかに関係なく、不要になったスレッドハンドルは自分でCloseHandle()を呼び出して開放してやる必要があります。(もちろんプロセス終了時には全てのハンドルがクローズされます)

mainuser
質問者

お礼

ご回答ありがとうございます。

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.1

Windowsですよね。この種の内容はOSによって異なりますのでご注意を。 >○シグナル状態と非シグナル状態とはどういう状態なのでしょうか? イベントを待つプロセス,スレッドが動作できる状態がシグナル状態、そうでないのが非シグナル状態です。 WaitForMultipleObjects()等でイベントを待っているスレッドなどはシグナル状態になるまで、 実行を止めて待ちます。 >○自動リセットの場合ではどのタイミングで切り替わっているのでしょうか? SetEvent()がないため、初期状態(非シグナル)のまま変化しません。 もし、どこかでSetEvent()が呼ばれた場合,その時点でイベントがシグナル状態になり、スレッドが動作し、 > DWORD r = WaitForMultipleObjects( 2, hEvent, FALSE, INFINITE ); のWaitForMultipleObjects()の関数から帰る時に、 非シグナル状態になります。 >○手動リセットの場合ではどのタイミングで切り替えればよいのでしょうか? プログラムの目的、内容等によります。 自動でなく手動にするなら何らかの目的があるはずなので。 特に何もなければ、自動と同じでいいでしょう・・というか、自動を使いましょう。 >○この2つの関数の役割の違いについて教えて下さい。 ExitThread()はスレッドを終了させるためのもので、 CloseHandle() はハンドルを閉じるための物です。 実際の処理内容は異なります。 例えば,ExitThread()が呼ばれてもスレッドハンドルはクローズされない場合があります。 >関数実行時にシグナル状態は気にする必要はありますか?(シグナル状態にしなくてよいのか? 処理内容によります。 まあ、フェイルセーフ,理解を深めるという意味で,常に気にしていた方がいいかも知れませんが。

mainuser
質問者

お礼

ご回答ありがとうございます。 でもまだイベントオブジェクトが理解できません・・・ >Windowsですよね。この種の内容はOSによって異なりますのでご注意を。 ・書き忘れていました。すみません。OSはWindowsXPです。 >>○自動リセットの場合ではどのタイミングで切り替わっているのでしょうか? >SetEvent()がないため、初期状態(非シグナル)のまま変化しません。 >もし、どこかでSetEvent()が呼ばれた場合,その時点でイベントがシグナル状態になり、スレッドが動作し、 >> DWORD r = WaitForMultipleObjects( 2, hEvent, FALSE, INFINITE ); >のWaitForMultipleObjects()の関数から帰る時に、 >非シグナル状態になります。 ・自動リセットは自動でシグナルと非シグナルを切り替えてくれるものだと思っていたのですが、間違っているのでしょうか? 「スレッドが動作できる状態=シグナル状態」なんですよね? 初期状態が非シグナルなのでこのまま変化しないということはスレッドはずっと動かないということですか? ・MSDNにはWaitForMultipleObjects関数はシグナル状態になったときに制御を返すとありますが、シグナル状態ではなく非シグナル状態になるのですか? それに初期状態に非シグナルを指定していてもちゃんと返ってきますが、これはどこかでSetEvent関数が呼ばれていると考えてよいのでしょうか? >>○この2つの関数の役割の違いについて教えて下さい。 >ExitThread()はスレッドを終了させるためのもので、 >CloseHandle() はハンドルを閉じるための物です。 >実際の処理内容は異なります。 >例えば,ExitThread()が呼ばれてもスレッドハンドルはクローズされない場合があります。 >>関数実行時にシグナル状態は気にする必要はありますか?(シグナル状態にしなくてよいのか? ) >処理内容によります。 >まあ、フェイルセーフ,理解を深めるという意味で,常に気にしていた方がいいかも知れませんが。 ・どういう時に使い分けをしたらよいのでしょうか? スレッドを使わなくなったときはどっちを使うべきでしょうか?それとも両方ですか? 質問が多くなってしまって申し訳ございません。

関連するQ&A

  • マルチスレッドプログラミングについて

    こんばんわ。 マルチスレッドプログラミングを行なっています。開発環境はVC++.NET2003でC言語を用いてコンソールアプリケーションを勉強中です。 以下にプログラムを示します。 以下のプログラムは、 (1)ThAとThBが交互に1~10までカウントUP (2)ThBだけが11~20までカウントUP (3)ThAはTh11から、ThBは21からカウントUP というプログラムを記述したつもりなのですが・・・実行開始後は(1)から(3)のように表示できるのですが、それ以降はThAとThBが交互に表示されてしまいます。 (1)から(3)を繰り返す記述の仕方はありますでしょうか? よろしくお願い致します。 HANDLE hEvent[3]; unsigned __stdcall ThB(void *lpx){ int j; int l=1; for(j=1;j<100;j++){ Sleep(100); printf("ThB%d\n",j); if(l%20==0){ SetEvent(hEvent[0]); } l++; } return 0; } unsigned __stdcall ThA(void *lpx){ int k; int j=1; for(k=1;k<100;k++){ Sleep(100); printf("ThA%d\n",k); if(j%10==0){ WaitForSingleObject(hEvent[0],INFINITE); } j++; } SetEvent(hEvent[2]); return 0; } int main(int argc ,char *argv[]){ unsigned int thID[2]; HANDLE hTh[2]; int i; hEvent[0] = CreateEvent(NULL, TRUE, FALSE, "CH0"); hEvent[1] = CreateEvent(NULL, TRUE, FALSE, "CH1"); hEvent[2] = CreateEvent(NULL, TRUE, FALSE, "MAINEVENT"); hTh[0] = (HANDLE)_beginthreadex(NULL, 0, ThA, NULL, 0, &thID[0]); hTh[1] = (HANDLE)_beginthreadex(NULL, 0, ThB, NULL, 0, &thID[1]); WaitForSingleObject(hEvent[2], INFINITE); for(i=0;i<2;i++) CloseHandle(hTh[i]); return 0; }

  • マルチスレッドプログラム

    いつもお世話になっております。 今回はマルチスレッドプログラムについてお聞きしたいです。 マルチコアCPUを使ってたとえば下記のようなことをしたいときに for (int i = 0; i < 1000000; i++) { sum += i; } このまま計算するよりもいくつかスレッドを作って、計算量を分散させてから最後に足してやるほうが早いと思いまして、 現在Core2Quadが手元にありましたのでスレッドを4つ作って スレッド1で0から250000まで スレッド2で250001から500000まで スレッド3と4も同様にして実際にやってみたのですが スレッドなしの状態よりも倍くらい時間がかかってしまうようになってしまいました。 計算結果は同じになり、CPU使用率もシングル時が25%、マルチ時が100%になっているので意図したようにはできていると思います。 GetProcessAffinityMaskを使って、各スレッドにひとつづつコアを割り当てても同様でした。 実際に時間が4分の1に近くなると思っていたのですが2倍かかってしまったので不思議です。 どなたか上記のことを思惑通りに動かせそうな方法をご存知の方はご教授願います。 プログラムは全部は無理ですが重要そうなところは下記のとおりです。 スレッド作成部分 {   DWORD dwStart = ::timeGetTime();   _thread_handle[0] = (HANDLE)::_beginthreadex(NULL, 0, thread_first, NULL, CREATE_SUSPENDED, &_thread_first_id);   _thread_handle[1] = (HANDLE)::_beginthreadex(NULL, 0, thread_second, NULL, CREATE_SUSPENDED, &_thread_second_id);   _thread_handle[2] = (HANDLE)::_beginthreadex(NULL, 0, thread_third, NULL, CREATE_SUSPENDED, &_thread_third_id);   _thread_handle[3] = (HANDLE)::_beginthreadex(NULL, 0, thread_forth, NULL, CREATE_SUSPENDED, &_thread_forth_id);   for (int num = 0; num < 4; num++)   {     ::ResumeThread(_thread_handle[num]);   }   ::WaitForMultipleObjects(4, _thread_handle, TRUE, INFINITE);   for (num = 0; num < 4; num++)   {     ::CloseHandle(_thread_handle[num]);   }   DWORD dwEnd = ::timeGetTime(); } 各スレッド部分 { HANDLE hCurrent = ::GetCurrentProcess(); DWORD pamask, samask, patmp = 0; int nRet = ::SetProcessAffinityMask(hCurrent, 0x0001); ::GetProcessAffinityMask(hCurrent, &pamask, &samask); DWORD dwStart = ::timeGetTime(); _result1 = 0; for (int multi = 0; multi < _multi; multi++) {   for (DWORD i = 0; i < 100000/4; i++)   {     _result1 += i;   } } DWORD dwEnd = ::timeGetTime(); time1 = dwEnd - dwStart; ::_endthread(); return 0; } 開発環境は WindowsXP SP3 VisualStudio6.0 ATL/WTLです。

  • WaitForMultipleObjects関数の待機状態から抜けるにはどうすればいいのですか。

    初心者です。XPとVC++ 6.0で開発しています。 シリアル通信プログラムを作成しておりますが、クロスケーブルでPC同士をつないで、片方はハイパーターミナル(以下H)を立ち上げて、もう片方は、作成しているプログラム(以下P)を走らせて通信しようとしています。Pから、Hへの送信はできるのですが、Hを走らせているPCのキーボードをたたいても、Pで受信ができません。WaitForMultipleObjects関数のところで待機状態になったままです。DEBUGの進め方についてアドバイスをいただけますでしょうか。 Pを実行した際には、GetLastError関数がERROR_IO_PENDINGを返しており、IOからのデータ待機状態に入っています。(※P,H共に、COM1,9600bps,8bit,NONEに設定しています。)ご教示お願いいたします。 // PURPOSE: This is the starting point for the Read Thread. DWORD WINAPI StartReadThreadProc(LPVOID lpvParam) { char szInputBuffer[INPUTBUFFERSIZE]; DWORD nNumberOfBytesRead; HANDLE HandlesToWaitFor[3]; DWORD dwHandleSignaled; DWORD fdwEvtMask; OVERLAPPED overlappedRead = {0, 0, 0, 0, NULL}; OVERLAPPED overlappedCommEvent = {0, 0, 0, 0, NULL}; overlappedRead.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); overlappedCommEvent.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); // We will be waiting on these objects. このイベントが立つまでRX動作は待機状態になる。 HandlesToWaitFor[0] = g_hCloseEvent1; HandlesToWaitFor[1] = overlappedCommEvent.hEvent; HandlesToWaitFor[2] = overlappedRead.hEvent; // Keep looping until we break out. while (TRUE) { // Wait until some event occurs (data to read; error; stopping). dwHandleSignaled = WaitForMultipleObjects(3,HandlesToWaitFor, FALSE, INFINITE); switch(dwHandleSignaled) { case WAIT_OBJECT_0: // Signal to end the thread. { // Time to exit. } case WAIT_OBJECT_0 + 1: // CommEvent signaled. { // Handle the CommEvent. // Start waiting for the next CommEvent. break; } case WAIT_OBJECT_0 + 2: // Read Event signaled. { // Get the new data! break; } case WAIT_FAILED: // Wait failed. Shouldn't happen. { goto EndReadThread; } default: // This case should never occur. { OutputDebugString("Unexpected Wait return value"); goto EndReadThread; } } // End of switch(dwHandleSignaled). } // End of while(TRUE) loop. // Time to clean up Read Thread. EndReadThread: OutputDebugString("Read thread shutting down\n"); PurgeComm(g_hCommFile1, PURGE_RXABORT | PURGE_RXCLEAR); CloseHandle(overlappedRead.hEvent); CloseHandle(overlappedCommEvent.hEvent); g_dwReadThreadID1 = 0; CloseHandle(g_hReadThread1); g_hReadThread1 = 0; return 0; }

  • タイマー関数とマルチスレッドについて

    こんばんわ。 マルチスレッドプログラミングを行なっています。 コンパイラはVC++.NETでC言語を利用しwin32 apiを用いています。 スレッドを_beginthreadex関数でスレッドを2つ生成し、WaitForSingleObject,SetEvent,ResetEvent関数によるイベント同期を利用し、2スレッドの同期をはかっています。 [質問内容] 以下のように、スレッド2でWaitForSingleObject関数にてスレッド2を待機状態にし、スレッド1のSetEvent関数にて待機しているスレッド2を再開させる方法をとっています。 例えば、タイマーをスタート後に待機状態になり、スレッド2が再開後タイマーストップするとした場合、スレッド2が待機状態のときもタイマーを動き続けているのでしょうか? ・スレッド1 SetEvent(hEvent[0]); ・スレッド2 SUSPEND_INTERVAL=20 if(Num%THREAD_SUSPEND_INTERVAL==0){ timestart=timeGetTime();←タイマースタート WaitForSingleObject(hEvent[0],INFINITE); ResetEvent(hEvent[0]); timestop=timeGetTime();←タイマーストップ } よろしくお願いします。

  • C++ GUIのメッセージループ。

    初心者です。 よろしくお願いします。 とても重く時間の掛かる処理を色んなサイトを参考にスレッドにしてみたんですけど、書き方が悪いのか、再描写がワンテンポ遅れたり、アプリケーションを複数起動したりするとフリーズしてしまったりします。 原因はメッセージループにあるような気がしてるんですが、この書き方はおかしいですか?? どのサイトから引用したのかわからなくなってしまいました。 気付いたことなどあったら何でもいいので教えて貰えたら嬉しいです!よろしくお願いします!! thread01に重い処理が書かれてます。 int thread_call() {   unsigned int dwThreadId[1];   HANDLE hThread[0] = (HANDLE)_beginthreadex(     NULL,     0,     ( unsigned int (__stdcall*)(void*) )thread01,     NULL,     0,     &dwThreadId[0] );   MSG msg;   DWORD dwRet = WAIT_TIMEOUT;   while ( 1 ) {     dwRet = ::MsgWaitForMultipleObjects( sL, hThread, FALSE, INFINITE, QS_ALLEVENTS );     if ( dwRet == WAIT_OBJECT_0 + sL ) {       if ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {         ::TranslateMessage( &msg );         ::DispatchMessage( &msg );       }     } else if ( dwRet >= WAIT_OBJECT_0 && dwRet < WAIT_OBJECT_0 + sL )       break;   }   CloseHandle( hThread[0] );   hThread[0] = NULL; }

  • (マルチスレッド)_beginthreadexに複数の引数を渡す

    現在プログラムでマルチスレッドをやろうとしているのですが、 マルチスレッドの関数に数値や配列などの引数を渡すことは可能でしょうか? MSDNで調べてみると、_beginthreadex関数の4番目のNULLのところに引数リストを 指定できるとあったのですが、その意味が良くわかりませんでした。 以下のプログラムの場合にマルチスレッドに変数a, b, cを引数として渡したい場合は どのように書けばいいのでしょうか? #include <stdio.h> #include <windows.h> #include <process.h> unsigned WINAPI MyThread( void *lpx ){ while (1) { printf("スレッド実行中\n"); Sleep(1000); } return 0; } void main(){ // スレッドに渡したい変数の宣言 int a = 128; int b = 256; int c = 512; // スレッドIDの宣言 DWORD thID; // マルチスレッドの開始 (HANDLE)_beginthreadex( NULL, 0, &MyThread, NULL, 0, (unsigned int*)&thID ); // ループ while (1) { printf("メイン関数実行中\n"); Sleep(2000); } }

  • マルチスレッド

    ウインドウズプログラミングを始めて1ヶ月弱の初心者です。 色々探してみたのですが、結局良く分かりませんでした。 宜しくお願いします。 以下のリンクにおいて、 http://wisdom.sakura.ne.jp/system/winapi/win32/win143.html 1)主スレッドとは、具体的にソースファイルのどこからどこまでのことを言うのでしょうか? そもそもスレッドとは何でしょうか?関数のことでしょうか? また、タスクとは、実行ファイルと考えて良いのでしょうか? 2)副スレッド(ThreadFunc)を作成すると、主スレッド(WinMain?)と副スレッドで並列処理をするとのことですが、CPUは普通一つしかないので、実際は、主スレッド(WinMain?)と副スレッドを常に切り替えながら動作すると思います。が、ここで疑問なのですが、主スレッドと副スレッドの切り替えはいつ誰が行うのでしょうか?また、切り替えタイミング(例えば1ms毎に切り替えたいとか)は自由に設定出来るのでしょうか? 3)"マルチスレッドは親プロセスのメモリ空間を共有します" とあるのですが、これは CreateThread(NULL , 0 , ThreadFunc , (LPVOID)hWnd , 0 , &dwID) の(LPVOID)hWnd を、副スレッド(ThreadFunc)に引数として渡しているから、つまり、主スレッドと副スレッドは、(LPVOID)hWnd だけがメモリを共有する、ということでしょうか? 主スレッドと副スレッドでメモリを共有すると、どんなメリットがあるのでしょうか? 4)マルチスレッドはこういう時に使うとよい、 というような大まかな判断基準があれば教えて下さい。 分かり辛い質問で申し訳有りません。宜しくお願い致します。

  • マルチスレッドでの画像描画

    マルチスレッドを使ってロード画面を作ろうとしているのですが、 上手く画像が描画更新してくれません。 スレッドの中身は下記の通りです。よろしくお願いします。 HRESULT GameMain::LoadScreen() { // スレッドの生成 static bool onlyonce_createthread = FALSE; if(onlyonce_createthread ==FALSE) { hTh = (HANDLE)_beginthreadex( NULL, // SECURITY_ATTRIBUTES 構造体へのポインタ 0, // 新規スレッドのスタックサイズ &loadthread, // スレッドの実行開始アドレス this, // 新規スレッドに渡される引数リスト 0, // 新規スレッドの初期状態 (unsigned*)&thID ); // スレッドのIDを格納するためのDWORD型変数へのポインタ onlyonce_createthread =TRUE; } // ローディング画面の描画 static bool loopflg = TRUE; while(loopflg) { int threadCondition = CheckThread( hTh ); switch(threadCondition) { case THREAD_RUNNING: if(graphloaded_flg ==TRUE) { EnterCriticalSection( &m_criticalSection ); load_item = (float)(load_item/MAX_LOAD_ITEM); LeaveCriticalSection( &m_criticalSection ); d2d_control->GaugeDraw(0, 0, load_item); Sleep(100); } break; case THREAD_EXIT: loopflg =FALSE; break; case THREAD_ERROR: return E_FAIL; break; } } return S_OK; }

  • 非同期のプロセス間通信(パイプ)で全データ受信する

    こんにちは。 非同期のプロセス間通信(パイプ)で詰まっています。 環境はWindowsで処理系はC++(Win32)です。 スレッドを用意して、 hPipe = ::CreateFile( L"\\\\.\\pipe\\pipename", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ; で作成し、OVERLAPPED構造体を // ZeroMemory( &so, sizeof( OVERLAPPED )) ; sOverlapped.hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; として、 const size_t bufsize = 16 ; BYTE     buffer[ uBufSize ] ; DWORD    dwNumberOfBytesRead ; bRet = ::ReadFile( hPipe, buffer, bufsize, &dwNumberOfBytesRead, &so ) ; で読み込みをしています。ReadFile関数はすぐ戻りbRetはFALSEで返ってくるため、GetLastErrorを調べて、 switch( ::GetLastError()) {   case ERROR_IO_PENDING :     bRet = ::GetOverlappedResult( hPipe, &so, &dwNumberOfBytesRead, FALSE ) ;     break ; } としてWaitForMultipleObjectsでsOverlapped.hEventがシグナル状態になったら取得したデータの処理をしています。 シグナル状態になるならないに関わらず、上記のReadFileとGetOverlappedResultはループでぐるぐる回しています。 上記の状態で短いデータならよかったのですが、上記のReadFileで読み込み最大サイズの16バイトを超えてしまとうと、 残りの部分のみしか取得できませんでした。 0123456789ABCDEFabcdefg というデータを受信しようとしたとき、後半のabcdefgだけしか取得できませんでした。 すべてのデータを正しく取得するにはどのようにしたらよいのでしょうか?

  • スレッドの再開

    MFCでアプリケーションを開発しています。 メインのプログラムを走らせながら計算処理を行いたくて、本やネット等のサンプルプログラムを見ながら別スレッドを生成してみました。 OnInitDialog()でイベントとスレッドを生成し、スタートボタンのクリック押下をトリガーとして、計算処理(Run())を呼んでいます。 タイマー開始後は一定時間ごと(サンプルでは500msec)にスレッドを再開して計算処理を実行し、計算処理完了後はスレッドを一時停止状態にしたいと思っています。 (アプリケーション起動時にサスペンドモードで起動したスレッドをボタン押下でResumeThread(再開)し、あとはタイマーでイベントシグナルをセットして制御するつもりでした。) ですが、下記のコードで走らせると、初回のみ計算処理が呼び出され、その後はスレッドが再開されません(ThreadProc()がコールされない)。 理解不足から何か考え違いをしているのだと思うのですが、どこをなおすべきかわからず行き詰まっています。 どなたかご指摘頂けたらと思います。よろしくお願い致します。 ※実際に記述したコードの抜粋になりますので計算やリソースの解放処理等は省略しています。 OS:Win10 開発環境:VisualStudio2015 C++ ---------------------------------------------------------------- BOOL CMFCApplication1Dlg::OnInitDialog() { CDialog::OnInitDialog(); 中略 … m_hEvent = CreateEventA(NULL, FALSE, FALSE, "EVENT"); m_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)this, CREATE_SUSPENDED, NULL); return TRUE; } void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent) { switch(nIDEvent) { case 1: { BOOL blRet = SetEvent(m_hEvent); } break; default: { } break; } CDialog::OnTimer(nIDEvent); } UINT CMFCApplication1Dlg::ThreadProc(LPVOID pParam) { CMFCApplication1Dlg* pDlg = dynamic_cast<CMFCApplication1Dlg*>(reinterpret_cast<CWnd*>(pParam)); if(pDlg) { pDlg->ThreadProcCall(); } return 0; } // LineProfileスレッド処理呼び出し. void CMFCApplication1Dlg::ThreadProcCall(void) { // イベントオブジェクト取得. HANDLE h = OpenEventA(EVENT_ALL_ACCESS, FALSE, "EVENT"); // シグナル状態になるまで待機. WaitForSingleObject(h, INFINITE); // 非シグナル状態に. ResetEvent(h); // 計算処理呼び出し. Run(); this->SendMessage(WM_USER_COMPLETE_PROC); } void CMFCApplication1Dlg::Run(void) { // 計算処理. } // LineProfileスレッド終了後処理. afx_msg LRESULT CMFCApplication1Dlg::OnCompleteProc(WPARAM wParam, LPARAM lParam) { // スレッド停止. DWORD dwRet = SuspendThread(m_hThread); return 0; } void CMFCApplication1Dlg::OnBnClickedBtnStart() { // スレッド再開. DWORD dwRet = ResumeThread(m_hThread); // 計算処理呼び出し用タイマー設定. m_nUpdatePaintTimer = SetTimer(1, 500, NULL); }