Threadの使い方について

このQ&Aのポイント
  • Threadの使い方に関する質問です。コード内でのSleep(1)の省略方法を教えてください。
  • コードの説明:OnButton5から30回ThreadAを起動し、ThreadAからThreadBを起動するコードです。Sleep(1)があるとcountAとcountBが30までカウントアップしますが、Sleep(1)がないとcountAとcountBが30までカウントアップしないことがあります。
  • 質問:Sleep(1)を省略できる方法はありますか?
回答を見る
  • ベストアンサー

Threadの使い方について

下記のコードは,OnButton5から、30回ThreadAを起動し、ThreadAからThreadBを起動する ものです。OnButton5の中にSleep(1)が有りますと、countXとcountA, countBは共に 30までカウントアップしますが、Sleep(1)がないと、countA, countBが30までカウントアップ しない事があります。 Q1) Sleep(1)を省略できる方法はありますか? void CMFCTHREADView::OnButton5(){ int i; for(i=0; i<LIMIT; i++){  //別途設定 #define LIMIT 30 if(SW_READYA==false){ //ThreadAがreadyになるのを待って起動する } SW_READYA=false; SetEvent(hEventA_start); //loop開始 InterlockedIncrement(&countX); //OnButton5 TRACE1("====countX=%d\n",countX); Sleep(1);//これがあると旨くいきます。 } } UINT ThreadA(LPVOID pParam){ int *pThis=reinterpret_cast<int*>(pParam); //pParam引数の受取方法 int aa=*pThis; while(SW_FIRST_LOOPX){ //=================================== if(WaitForSingleObject(hEventSW_A, INFINITE)){ //スタートコマンド待ち AfxMessageBox("time_over of hEventSW_A"); } ResetEvent(hEventSW_A); TRACE("ResetEvent(hEventSW_A)\n"); while(LOOP_ON){ //LOOP_ON is off by endOfTransferWAVE //======================= if(WaitForSingleObject(hEventA_start, INFINITE)){ //スタートコマンド待ち } ResetEvent(hEventA_start); countA++; if(SW_READYB==false){ //ThreadBがreadyになるのを待って起動する } SW_READYB=false; SetEvent(hEventB_start); //threadBの開始 TRACE1("countA=%d\n", countA); SW_READYA=true; //======================= } } return TRUE; } UINT ThreadB(LPVOID pParam){ int *pThis=reinterpret_cast<int*>(pParam); //pParam引数の受取方法 int aa=*pThis; while(SW_FIRST_LOOPX){ if(WaitForSingleObject(hEventSW_B, INFINITE)){ //スタートコマンド待ち } ResetEvent(hEventSW_B); TRACE("ResetEvent(hEventSW_B)\n"); while(LOOP_ON){ //LOOP_ON is off by endOfTransferWAVE if(WaitForSingleObject(hEventB_start, INFINITE)){ //スタートコマンド待ち AfxMessageBox("time_over of hEventB_start"); } ResetEvent(hEventB_start); countB++; TRACE1("countB=%d\n", countB); SW_READYB=true; } } return TRUE; } //================= 以上、宜しくお願いします。

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8525/19380)
回答No.1

このような場合は Sleep(0); を使います。 Sleepに0を指定した場合、自分より実行順位が等しいか又は高いスレッドがあれば、それらに実行権を譲り、無ければ(自分が一番優先度が高ければ)即座に戻って来ます。 つまり「0を渡せば時間待ちしないで、実行権の明け渡しをする」ので、他のスレッドが期待通りに動作します。 マルチスレッドで「他のスレッドが実行されるのを期待(想定、待機)する場合」は「Sleep(0)を実行して明示的に実行権の明け渡し」をしないといけません。

関連するQ&A

  • スレッドについて

    スレッドについて勉強中なのですが、簡単なスレッド作り、 スレッドの処理が終わってからメインの処理を行わせたくて 以下のようなプログラムを書いてみました。 そこで、WaitForSingleObjectを使ってスレッドが終了するのを 待ちたいのですが、WaitForSingleObjectではまってしまうようで sprintfのメッセージ(スレッドが止まってしまっている)が 表示されません。 WRITE関数の処理が終われば、、WaitForSingleObjectで処理が 戻ってくると考えているのですが…。 スレッドについてと、間違いについて教えてもらえないでしょうか? 宜しくお願いします。 main { if(!stop) {   File = CreateFile(...); g_hThead = CreateThread(NULL,0,WRITE,(LPVOID)NULL,0,NULL); g_stop = false; }else { g_stop = true; ::WaitForSingleObject(g_hThead, INFINITE); CloseHandle(File); CloseHandle(hThead ); } } void WRITE() { while(!g_stop) { WriteFile(...); } ...処理を行う sprintf("スレッドを終了します。") }

  • VS2008のMFCのTextOutについて

    毎度、お世話になります。 Windows7でVS2008のMFCのFormView形式でプログラムしています。 OnButton5でTextOut文を実行していますが、最後の『pDC->TextOut(20,80,str)』 だけ表示されます。 但し、前の2個のpDC->TextOutの後にSleep(1)を追加しますと、全て表示できます。 Q1)Sleep(1)を追加しなくて、全てのTextOutが表示できる方法はありますか? ================================ void CMFCTHREADView::OnButton5(){ // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください CDC* pDC=this->GetDC(); int t_endB=999; str.Format("time=%d ms ",t_endB); pDC->TextOut(20,40,str); //これだけ表示されず。 //=============== str.Format("countX=%d ",countX); pDC->TextOut(20,60,str); //これだけ表示されず。 //=============== str.Format("countA=%d countB=%d ",countA,countB); pDC->TextOut(20,80,str); //これだけ表示されます。 //==================== } =================================== 以上、宜しくお願いします。

  • スレッドについての質問です。

    下記のロジックを見ていただきたいのです。 スレッドがnullの間はrunが動いています。 問題は一番下に記載した"stopplay()"というメソッドだと思われます、スレッドを停止して直ぐにまた動かしていますがどうもスレッドが二つ動いている様子です。なぜでしょうか? ************************************************** //最初にスレッドを開始します。 public init(){ play(); } ************************************************** //スレッドのON OFF public void threadOnOff(boolean sw) { if(sw == true){ thread =new Thread(this); thread.start(); } else { thread = null; } } ************************************************** //スレッド開始 public void play(){ threadOnOff(true); } ************************************************** //スレッド停止 public void stop(){ threadOnOff(false); } ************************************************** //runメソッド  public void run(){ String mode = ""; while(thread != null){ try { thread.sleep(500); //0.5秒間隔で動きます。 mode = modeRequest(); if(mode.startsWith("STOP") == true) { //スレッド停止 threadOnOff(false); } } catch (InterruptedException ie) {} } } ************************************************** //問題のメソッドです。 public void stopplay(){ stop(); play(); }

    • ベストアンサー
    • Java
  • [VC++] AfxBeginThreadで生成したスレッドの監視方法について

    お世話になります。 VC++でスレッドプログラムを作っています。 AfxBeginThreadでワーカースレッドを作成し、その中でダイアログを表示する プログラムです。 問題は、ワーカースレッドがある処理状態に至ったことを メインスレッドで検知したいのですが、それがうまく いかないということです。 コードの概略をしめします。 <メインスレッド側> void CTestApp::OnTest() {   CTestDlg dlg;   dlg.IsContinue = FALSE;   pThread = AfxBeginThread(TestDlg::Thread, (void*)&dlg);   while (!dlg.IsContinue) { // <----問題:このループ処理を抜けれない!    Sleep(0);   } } <ワーカースレッド側> UINT TestDlg::Thread(LPVOID pParam){   TestDlg* pDlg = (TestDlg*)pParam;   pDlg->Create(TestDlg::IDD);   pDlg->ShowWindow(SW_SHOW);     pDlg->IsContinue = TRUE; //<--ここでフラグを変更しているのに。   while(pDlg->IsContinue) {    MSG msg;    if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {      ::TranslateMessage(&msg);      ::DispatchMessage(&msg);    }   }   pDlg->DestroyWindow();   return 0; } ---- メインスレッドのSleep(0)で待つのを AfxGetApp()->PumpMessage()に変更すると ループを抜けるようなのですが、どうも納得できません。 上記のプログラムで問題、もしくはプロジェクトの 設定等に不備がある可能性がありましたら 御教授いただけたら幸いです。 よろしくおねがいいたします。

  • プログラムのスレッド化について。

    以下の処理をスレッド化しようとしています。 public class FCP{ int N=10 long LOOP_MAX=100 double x[][] = new double[N][4] int g[][] = new int[N][4] boolean y[][] = new boolean[N][4]//出力 boolean A[][] = new boolean[N][10] double T=0.5 Set_Adjacent_Matrix() //A配列にtrueとfalseを代入 Set_initial_value() //y配列に初期値を代入(Math.random()>0.5) g1(int i, int j) //k<4 sum=1 if( y[i][k] == true ) --sum return(double)sum g2(int i, int j) //k<N sum=0 if( y[i][j] == true ) if( y[k][j] == true && A[i][k] == true ) --sum return(double)sum Display_output() //結果表示 if( y[i][j] ) System.out.print("0") else System.out.print(".") public static void main(String args[]) { long loop; int i, j, k; Set_Adjacent_Matrix(); Set_initial_value(); for( loop=0; loop<LOOP_MAX; loop++ ){ for( i=0; i<N; i++ ){ for( j=0; j<4; j++ ){ x[i][j] = g1( i, j ) + g2( i, j ); if( y[i][j] ){ x[i][j] += T; }else{ x[i][j] -= T; } if( x[i][j] > 0.0){ y[i][j] = true; }else{ y[i][j] = false; } } } Display_output(); } } 今回Threadクラスの継承を使ってスレッド化しようと考えました。runメソッドには上のプログラムのmain部分の処理をさせようと思っています。そしてstartメソッドで必要な数(Nの値=10コ)のスレッドを生成しrunメソッドを実行する。 と、ここまではわかったのですが、「生成された各スレッドの番号を保持し、そのスレッドに担当させる処理を決める」という部分をどうすればいいのかわかりません。 「i(1~10)番目のスレッドはN(1~10)列目の処理を担当している」という風にするにはどうしたらいいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • スレッドとメッセージキューに関して

    現在、下記のようなプログラムを作成しています。 内容は、メッセージキューを受信するスレッドを生成するというイメージです。 処理内容は下記のようになります。  (1)メッセージキューの生成  (2)スレッド生成(メッセージキュー受信側)  (3)スレッド停止  (4)メッセージキューの削除 しかし、(3)のスレッド停止を実施しても、(4)のメッセージキューの削除以降にて、msgrcvのエラーが出力されてしまいます。 スレッド停止を行ったことから、TestThreadは動作しなくなり、(4)のメッセージキューの削除にて、エラーともならずに終了することを望んでりますが、上手くいきません。 下記に作成しているプログラムを記載いたします。 正常終了をするには何がいけないのでしょうか? ご教授宜しくお願い致します。 [test.cc] ---------------------------------------------------------------- #include <time.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <ctype.h> #include <stdlib.h> #include <pthread.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> // メソッドポインタ定義 typedef void (*testT); // スレッドID pthread_t threadId; // メッセージキュー識別子 int msqId; // 送受信するメッセージ struct msgbuf{ long int type; char data[BUFSIZ]; }; // テストスレッド void TestThread() { // メッセージ struct msgbuf message; while( 1 ) { printf("### TEST ###\n"); printf("msq start\n"); // 受信 if( msgrcv( msqId, &message, BUFSIZ, 0, 0 ) == -1) { printf("ERR! msgrcv errno[%d]\n", errno); continue; } printf("msq ed\n"); sleep(1); } return; } // メイン int main(int argc, char *argv[]) { // メッセージキュー識別子退避変数 int testMsqid; // スレッド操作リターン値 int status; // スレッドa用のパラメータ pthread_t thread_test; printf("### TEST START ###\n"); // メッセージキューの作成 if( (testMsqid = msgget((key_t)1111, 0666 | IPC_CREAT)) == -1 ) { printf("ERR! CREATE bkMsqId[%d]\n", testMsqid); return 1; } // メッセージキュー識別子を共通変数に設定 msqId = testMsqid; printf("msgget OK\n"); sleep(5); // スレッドを生成 status = pthread_create(&thread_test, NULL, (void*(*)(void*))TestThread, (void*)NULL); if(status!=0) { printf("pthread_create ng\n"); return 1; } printf("pthread_create OK\n"); sleep(5); // スレッド停止 status = pthread_cancel(thread_test); // スレッド停止結果 if ( status != 0 ) { printf("pthread_cancel ng\n"); return 1; } printf("pthread_cancel OK\n"); sleep(5); // メッセージキューの削除 if ( msgctl( msqId, IPC_RMID, NULL) == -1 ) { printf("msqId[%d] errno[%d]\n", msqId, errno); return 1; } printf("msgctl OK\n"); sleep(5); printf("### TEST E N D ###\n"); return 0; } ----------------------------------------------------------------

  • マウスクリックで別のスレッドを動かしたい

    うまく動きません、どなたかご教示下さい(文字数が不足です) ===== public class ImgMove3 extends Applet implements Runnable , MouseListener { private int width , height ; private Thread th1 /*, th2*/ ; private boolean bLoopEnd = false ; private int x1 = 30 , y1 = 100 ; // private int x2 = 80 , y2 = 150 ; Image img1 , img2 ; AudioClip sound ; private int vx1 = 3 , vy1 = 2 ; // private int vx2 = 1 , vy2 = 1 ; Dimension d ; public void init() { d = getSize() ; width = d.width ; height = d.height ; this.addMouseListener(this) ; this.addMouseListener(new MyImage3(this)) ; img1 = getImage( getDocumentBase() , "ambulance.jpg" ) ; img2 = getImage( getDocumentBase() , "firecar.jpg" ) ; sound = getAudioClip( getDocumentBase() , "UFO.wav" ) ; } public void mouseEntered( MouseEvent e) { sound.play() ; } public void mouseClicked(MouseEvent e) { } public void start() { if(th1 == null) { th1 = new Thread(this); th1.start(); } } public void stop() { if( th1 != null ) { th1 = null ; } } public void run() { while(bLoopEnd == false) { move() ; repaint() ; try{ Thread.sleep( 10 ) ; } catch (InterruptedException e ) {} } } private void move() { if( x1 >= width - 130 ) { vx1 =- vx1 ; } if( y1 >= height - 110 ) { vy1 =- vy1 ; } if( x1 < 0 ) { vx1 =- vx1 ; } if( y1 < 0 ) { vy1 =- vy1 ; } } public void update( Graphics g1 ) { paint( g1 ) ; } public void paint( Graphics g1 ) { g1.drawImage( img1 , x1 , y1 , this ) ; } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e){ } } //======================================================================= class MyImage3 extends Applet implements Runnable , MouseListener { private int width , height ; private Thread th2 ; private boolean bLoopEnd = false ; private int x2 = 80 , y2 = 150 ; Image img2 ; AudioClip sound ; private int vx2 = 1 , vy2 = 1 ; Dimension d ; Image firecar ; ImgMove3 imv3 ; public MyImage3(ImgMove3 app) { imv3 = app ; imv3.img2 = getImage( getDocumentBase() , "firecar.jpg" ) ; } public void mouseEntered( MouseEvent e) { imv3.sound.play() ; } public void mouseClicked(MouseEvent e) { Graphics g1 =getGraphics(); g1.drawImage( img2 , x2 , y2 , this ) ; imv3.repaint(); } public void start() { if(th2 == null) { th2 = new Thread(this); th2.start(); } } public void stop() { if( th2 != null ) { th2 = null ; } } public void run() { while( th2 != null && bLoopEnd == false) { move() ; imv3.repaint() ; try{ Thread.sleep( 10 ) ; } catch (InterruptedException e ) {} } } private void move() { if( x2 >= width - 130 ) { vx2 =- vx2 ; } if( y2 >= height - 110 ) { vy2 =- vy2 ; } if( x2 < 0 ) { vx2 =- vx2 ; } if( y2 < 0 ) { vy2 =- vy2 ; } x2 += vx2 ; y2 += vy2 ; } public void update( Graphics g1 ) { imv3.paint( g1 ) ; } public void paint( Graphics g1 ) { g1.drawImage( img2 , x2 , y2 , this ) ; } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }

    • ベストアンサー
    • Java
  • スレッド動かず

    本の真似をして、スレッドを書いてみたんですがに何も起こりませんでした。全く分かりません。どうすれば良いでしょうか? public class Frame1 extends Frame implements Runable{ ................. ................. Thread kick = new Thread(this); int time; public void start() { if (kick ==null) kick.start(); } public void run() { while (kick == Thread.currentThread()) { time++; String s = Integer.toString(time); textArea1.append( s + "\r\n"); try{ Thread.sleep(1000); }catch(InterruptedException e){} } }

    • ベストアンサー
    • Java
  • 「キャンセル」ボタン付きの処理中ダイアログ

    Windowsアプリで、ある時間のかかる処理を キャンセルボタン付処理中ダイアログを表示し、途中で処理をキャンセル可能にしたいと考えています。 ここの過去ログから上記はマルチスレッドにする必要があると拝見しました。http://oshiete1.goo.ne.jp/kotaeru.php3?q=96951 <メイン画面の開始ボタン処理> ------------------ void C_SampleDlg::OnStart(){  CWinThread *cwt;  C_CancelDlg dlgCancel(this);  cwt = AfxBeginThread(Sample_Proc, &InputParams);  cwt->m_bAutoDelete = FALSE;  cwt->ResumeThread();  EnableWindow(FALSE);  dlgCancel.Create();  dlgCancel.ShowWindow(SW_SHOW);  while(TRUE){   if(dlgCancel.CheckCancel() == TRUE){    // キャンセルが押された時    EnableWindow(TRUE);    dRcd = WaitForSingleObject(cwt->m_hThread, INFINITE);    if(dRcd == WAIT_OBJECT_0)     return;   }   dRcd = WaitForSingleObject(cwt->m_hThread, 0);   if(dRcd == WAIT_OBJECT_0){    dlgCancel.DestroyWindow();    EnableWindow(TRUE);    break;   }  }  return; } <プロシージャ> ---------------------------------- UINT Sample_Proc(LPVOID pParam){  C_SampleDlg->やりたい処理関数呼び出し  ::AfxEndThread(0);  return 0; } 以降別ソース ================================== <C_SampleDlg::やりたい処理関数> ↑ここでdlgCancel.CheckCancel() == TRUEかどうか 判定したい場合、グローバル関数を使うか、または呼出し元で作成したインスタンスをパラメタとして渡して使うべきなのでしょうか。文字数の関係で分かりにくいところもありますが、よろしくお願いします。 ※dlgCancel.CheckCancel()はC_CancelDlgクラスのプロテクト変数を内部で操作しています。

  • スレッドの終了を知りたい(WindowsAPI)

    CreateThread()で作成したスレッドの終了を知りたい (具体的には、スレッドが終了するまで待機したい)のですが、 うまくいかず困っています。WindowsAPIに関する本やネットで調べた ところ、WaitForSingleObject()が適用できると考え、 以下のようなプログラムを作成したのですが、 元のスレッドがWaitForSingleObject()のところで 止まると同時に、CreateThread()で作成されたThread_1()も 止まってしまいます。アドバイスいただけますでしょうか。 ----プログラム(該当部分)ここから---- DWORD Thread_1(LPVOID param) {  int i;  char buff[128];  /* iが99のときのみ終了してよい */  while(g_iFlg == 1)  {   for(i = 0; i < 100; i++)   {    Sleep(100);    wsprintf(buff, "%d", i);    SetDlgItemText((HWND)param, IDC_STATIC_1, buff);   }  }  ExitThread(0);  return 0; } BOOL CALLBACK Proc_2(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {  switch(uMsg)  {   case WM_INITDIALOG:    g_iFlg = 1;    g_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_1, (LPVOID)hDlg, 0, &g_dwThread);    return TRUE;   case WM_COMMAND:    switch(LOWORD(wParam))    {     case IDC_BUTTON_CANCEL:     case IDCANCEL:      g_iFlg = 0;      WaitForSingleObject(g_hThread, INFINITE);      CloseHandle(g_hThread);      EndDialog(hDlg, 0);      return TRUE;    }  }  return FALSE; } ----プログラム(該当部分)ここまで----