• ベストアンサー

マルチスレッドにする必要がありますか?

<プログラム環境> Windows XP VC++6.0 MFC AppWizard(exe) ダイアログベース シングルスレッド <目的のプログラム仕様> ・ダイアログのボタンを押すとOnボタン関数に入る ・Onボタン関数で関数1(無限ループ)と関数2(無限ループ)を実行する ・関数1はnDataの内容を更新し続ける(37回/sec) ・関数2はnDataの内容を基に、数秒かかる処理を10秒毎に行う <今の知識で出来るコーディング> void Onボタン関数(){  int nData[10];  関数1(nData);  関数2(nData); } void 関数1(int nData[]){  for(;;) for(int i=0;i<10;i++) nData[i] = 更新データ; } void 関数2(int nData[]){  int nTotal=0;  DWORD dwOldTime = clock();  for(;;){   if(clock() - dwOldTime >10000){//10秒経過で実行    dwOldTime = clock();    for(int i=0;i<10;i++) nTotal += nData[i];//実際は数秒かかる程の処理    nTotal = 0; //初期化   }  } } <問題点> 今の知識で出来るコーディングでは、関数1の無限ループから処理が 他へ移ることは無く、関数2を実行する事が出来ません。 関数2の合計を計算する処理は、実際には数秒かかるので、 関数1で関数2を呼び出すことが出来ません。 (関数1は37回/secでデータ更新しなければならないので) <質問> 目的のプログラム仕様を満たすには、マルチスレッドにしなければ ならないでしょうか? シングルスレッド、マルチスレッド、どちらの方法でも良いので、 どのようにコーディングすれば良いのか教えて下さい。 宜しければ、ご指摘お願い致します。

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

nDataの同期は必要なんでしょう 10秒ごとに関数Bを実行するのですが これは 関数Aで収集した10秒間分のデータが対象なのでしょうか そうなると データのバッファが足りないですね 関数Bを実行している間も 関数Aでの収集があるのでしたら 10秒間ぎりぎりのバッファでは 計測器からのデータの取りこぼしが懸念されます 1回のデータが10バイト 関数Bの最悪のケースの場合5秒かかるとするなら 少し余裕を見て20秒分のバッファ 740( 20 * 10 * 37 )バイト必要でしょう マルチスレッドにするなら CWinThreadクラスで ワーカースレッドを作成する方法調べてみましょう この際に スレッドの実行本体 ThreadProc内でイベントを待ち受けるように WaitForSingleObjectなどで待機させます 関数A側で既定のデータを収集できたら関数Bを待機させるために使った Eventハンドル(またはCEventクラスオブジェクト)をPulseEventまたはSetEventなどで反転させて関数Bの本体を実行しましょう Eventハンドルなどは 自動リセットイベントなどが手間がなくていいかもしれません バッファデータのどの範囲が関数Bで扱うのかはThreadProcに渡す LPVOIDのパラメータにて行うようにしましょう

meeyooyoo
質問者

補足

redfox63様、有難うございます。 nDataは10個のデータを上書きしているので、バッファは10バイト分で十分です。 データ上書きを一秒間に37回行うことで、常に最新のデータ10個 が得られる感じです。 10秒毎に、その時点で最新の10個のデータを使って処理する。 といったイメージです。 CWinThreadクラスで ワーカースレッドを作成する方法について、 ネットで調べたのですが、良く分かりませんでした。 ネット上のプログラムをコピーしても、エラー多発でした。 基本的な部分のコーディングを教えて頂けないでしょうか? ワーカースレッドが作成できましたら、WaitForSingleObjectなどで イベント待ちにしたいと思います。 宜しければご指摘お願い致します。

その他の回答 (1)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.1

関数1と2は全く関連が無い(同期をとらなくてよい)のでしょうか? もし、そうであるなら、マルチスレッドになるでしょう。 http://msdn.microsoft.com/ja-jp/library/cc429080.aspx あと、if(clock() - dwOldTime >10000){//10秒経過で実行 こういうことをすると、CPUを無駄使いするので、Sleepとか、タイマ 割り込みを考えるべきです。もの凄くもったいないです。

meeyooyoo
質問者

補足

nda23様、有難うございます。 CreateThreadについて、ネットで調べたのですが、使い方が 理解出来ませんでした。 CreateThreadはどこで実行するのでしょうか? Onボタン関数()の中でしょうか? どのようにコーディングするのか教えて頂けますと幸いです。 CPUを無駄使いしないように、割り込みを使うようにします。 宜しければご指摘お願い致します。

関連するQ&A

  • マルチスレッド内のループについて

    こんにちは。 開発環境は VC++6.0 SDI マルチスレッドがあり、2つの処理を行う関数が書かれています。 このスレッドはダイアログボックスに配置したストップボタンを押すとフラグFALSEになりループを終了させます。 2つの関数は、int型の整数を引数にして、処理を行います。 整数はある値に達すると 0 になり永遠にループを続け、2つの処理を行います。 と言う意味合いでプログラムを書きました。(書いたつもりです) (1)この書き方ですと、for内のループが動いている時に、右上の×ボタンでダイアログを閉じると [Debug Assertion Failed!]と言う警告文が出て強制的に終了してしまいます。 ストップボタンを押してもcount=10になるまではループしています。(当然ですが・・。) そもそもマルチスレッドの中にこのような形でfor文を入れるのは間違っているのでしょうか? どのような書き方にすれば良いのでしょうか? よろしくお願い致します。 bool m_flags;//スレッド内の処理を続けるか示すフラグ UINT CabcDlg::thread(LPVOID pParam)// { CabcDlg *pInst = (CabcDlg *) pParam; while(pInst->m_flags){//ストップボタンが押されると終了する。 for (int count = 0; count<10; count++ ) { pInst->OnSend(count); //処理A pInst->OnReceive(count);//処理B } } return 0; }

  • C++マルチスレッド処理について

    こんにちは 現在スレッドを作成して,マルチスレッド処理をしようとしているのですが, 全然理解できないので皆様のお力をお貸し下さい。 やりたい事は, (1) メインスレッドからスレッド1を作成。 (2) スレッド1では,ひたすらファイルなどからデータを取得させる。(読み込めなくなるまで) (3) メインスレッドでは,時々スレッド1を止めて,再度処理を続行させたい。 class Sample { public: // Sampleオブジェクト作成,同時にスレッド1を作成 Sample* create(); // スレッド1を止めて,再度動かす void process(); private: // この関数をスレッド1で処理させる // 内部では,読み込めなくなるまで無限ループ? void get(); }; スレッドに関してはイメージが湧くのですが, mutex (必要ですか?) に関しては一向に理解できません。 何を排他制御するのでしょうか。オブジェクト? 関数? 複雑ではなさそうなのですが,今までシングルスレッドの処理のみ書いていたため ピンときません。 よろしくお願い致します。

  • C++のvolatileについて

    C++のvolatileについて volatileはマルチスレッドやメモリマップドi/oに使われるようですが、volatileの概念や使い方がさっぱり分かりません。 Webサイトで調べてもあまり意味が分からないし、参考になるサイトがなかなか見つからないので、ここで質問しました。 volatileでマルチスレッドを使った例のコードを教えてください。 また、以下のコードでは、「while文の中でloopの値を変更していないので、これはシングルスレッドでは単なる無限ループになり、あまり意味のない処理になる。ところが、マルチスレッドの場合は別のスレッドからloopの値を変更される可能性があるため、意味のある処理になる」というものですが、これはどういうことでしょうか。 ------------------------- bool loop; void Hoge(){ loop=true; int n=0; while(loop){ ++n; } cout << n << endl; } ------------------------- 上記のコードは、そのままでは無限ループになる。マルチスレッドにしてloopの値を変更するにはどうしたら良いでしょうか。

  • マルチスレッドのスレッド数を増やしたい

    <プログラム環境> Windows XP VC++6.0 MFC AppWizard(exe) ダイアログベース <質問概略> CWinThread*を使って無限ループのスレッドを作ったのですが、 無限ループのスレッドをもう一つ作り、同時に実行しようとするとアクセスバイオレーションのエラーでます。 複数スレッドの作り方を教えていただけますと幸いです。 <質問詳細> 現状の正常に実行できるソースの必要最小限を書きます。 <.h> class CMyDlg : public CDialog{ public:   static UINT ThreadFunc( LPVOID pParam );   void Thread(); // スレッドの処理 protected:   CWinThread* m_pThread;//スレッドのアドレス }; <.cpp> void CMyDlg::OnButton(){   m_pThread = AfxBeginThread( ThreadFunc, this );   for(;;) /*無限ループ処理1*/ ; } UINT CMyDlg::ThreadFunc( LPVOID pParam ){   ((CMyDlg*)pParam)->Thread();   return 0; } void CMyDlg::Thread(){   for(;;) /*無限ループ処理2*/ ; } これに、 void CMyDlg::Thread2(){   for(;;) /*無限ループ処理3*/ ; } のようなスレッドを追加したいのですが全然出来ません。 宜しければご指摘お願い致します。

  • (マルチスレッド)_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); } }

  • なんで一瞬で処理が終わるの?

    時間を計測するプログラムを書いたのですが、何故か一瞬で処理が終わってしまいます。 #include <stdio.h> #include <time.h> int main(void){ int i,j,a,b=1; clock_t t; t=clock(); for(i=0;i<1000000000;i++){ for(j=0;j<10000000;j++){ a=b; } } printf("%.3f秒\n",(clock()-t)/1000.0); printf("%f %f",clock(),t); return 0; } 実行結果 0.000秒 0.000000 0.000000 なんで0なんでしょうか・・。

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

    マルチスレッドプログラミングについていくつか教えて下さい。 マルチスレッドの基礎がまだ分かってないので初心者でも分かり易いようにお願いします。 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 ); }

  • ポインタのポインタの関数受け渡しについて

    現在ポインタのポインタを利用したプログラムを作成しています。 main関数で int **dt; と宣言したとして、配列のセットにはset関数を、 表示に関する処理をpt関数で行いたいと思っています。 void set(int ??); void pt(int ???); int main(void){ int **dt; set(??); pt(???); } void set(int ??){ dt = (int**)malloc(sizeof(int*) * k); for(i = 0; i < k; i++){ dt[i] = (int*)malloc(sizeof(int*) * k); } のように配列サイズの動的確保が目的 } void pt(int ???){ 二重forループ{ printf(dt[i][j]); } } ??、???には何を入れるべきかが理解できません。 ご教示のほどよろしくお願いいたします。

  • clock関数は正確じゃないの?

    clock関数で時間を計測するとどうも狂ってしまいます。 おかしいので、このようなプログラムでclock関数の精度を調べてみました。 #include <stdio.h> #include <time.h> int main(){     int i,j;     clock_t start;     for(i=0;i<50;i++){         start = clock();         for(j=0;j<3000000000;j++);         printf("%4.3f秒\n",(double)(clock()-start)/CLOCKS_PER_SEC);         }     return 0; } このプログラムの実行結果はこちらです。 1.672秒 1.672秒 1.672秒 1.672秒 1.687秒←● 1.672秒 1.672秒 1.672秒 1.672秒 1.672秒 1.671秒 1.672秒 1.672秒 1.672秒 1.688秒←● ・・(略) 若干1.672で落ち着いているかと思いきや、時々狂っています。 この狂いは何が原因なんでしょうか? しかも狂うときは0.01位、結構ガツンと狂います。 しかもその狂い←●が等間隔で現れるのかと思いきや、そうでもありません。 この一見そろっているようで、時々ガツンと狂うのは何故なんでしょうか?

  • Javaアプレットとマルチスレッドの組み合わせ

    Javaアプレットとマルチスレッドを組み合わせてパラパラ漫画のようなものを作りたいのですがうまくいきません。 import java.awt.Graphics; import java.awt.Image; public class kadai4 extends java.applet.Applet implements Runnable{ Image logoImage[]; Thread runner; int current; int last=6; public void init(){ logoImage=new Image[last]; for(int i=0;i<last;i++){ logoImage[i] = getImage(getCodeBase(),"image/logo" + (i+1) + ".gif"); } } public void start(){ if(runner == null){ runner = new Thread(this); runner.start(); } } public void stop(){ if(runner != null){ runner.stop(); runner=null; } } public void run(){ while(true){ for(int i=0;i<last;i++){ current=i; repaint(); pause(400); } } } public void paint(Graphics g){ g.drawImage(logoImage[current],50,25,50,50,this); } void pause(int time){ try { Thread.sleep(time);} catch (InterruptedException e) {} } } これを実行すると推奨されない API を使用またはオーバーライドしています。というエラーが発生するのですがどうすれば良いでしょうか?他の方法でも構いません

    • ベストアンサー
    • Java

専門家に質問してみよう