• 締切済み

[MFC]AfxBeginTreadでのスレッド強制終了の方法について

WinInetで多数のクライアントとHTTP通信を行うプログラムを作成しています。 やりたい事は閉じたネットワークの中で 生きているホストを調べるということです。 HTTP_GETの可否で判断させるつもりですがpingでも構いません。 (DHCPサーバーのリース情報などは参照できない状態環境) 逐次処理で一台ずつタイムアウトは待ってられないので ホストの台数分だけスレッドを作成します(クラスCなら256台分)。 <!-- コード --> UINT MyThreadProc(LPVOID pParam) {  CMyHost* hostData = (CMyHost*)pParam;  hostData->Get();  return 0; } void CMyDlg::OnStart() {  CMyHost hostData[hostNum];  CWinThread* pThread[HostNum];  // 台数分スレッド起動  for (int i=0;i<(int)HostNum;i++) {   hostData[i].ipAddr = NetworkAddress + (DWORD)i;   pThread[i] = ::AfxBeginThread(MyThreadProc, &hostData[i]);  }  // 何秒か待つ  HANDLE timer = CreateWaitableTimer(NULL, FALSE, NULL);  WaitForSingleObject(timer, 10000);  // returnしてないスレッドがあっても全スレッド強制終了  /* 強制終了の仕方が分からない */ <!-- コードここまで --> 強制終了させるためには各スレッドにメッセージを投げて スレッド側でそれを判定するなどでしょうか? でも通信の終わってないスレッドは通信処理の最中なのだから どうやってメッセージを受け取ればいいのか想像つかないです。 (そもそもCInternerSessionでタイムアウトの使い方がよく分からない…、 もっとスマートな方法があれば教えていただきたいです。)

みんなの回答

  • hiochi
  • ベストアンサー率50% (1/2)
回答No.3

WaitForSingleObjectを使っておられるようなので、WaitForMultipleObjectsを使って、終了用のイベントを追加してはいかがでしょう? 終了イベントとタイマーの両方を待っておき、終了させたいタイミングでseteventして、WaitForMultipleObjectsを抜け、抜けた後どっちのイベントだったか判断してもう一回待つなり、そのままスレッドを終了するなり処理をするイメージです。

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.2

基本的なことから述べます。 通信といっても色々あります。 例えば、インターネットに公開するファイルサーバーなどで、 何MByteもあるファイルをたくさんDLさせる場合などでしたら、 アクセスが集中した場合、CPUがパンクする恐れもありますので、 特殊な技術が必要です (複数のサーバーに負荷分散するなど) しかし、一般的な機械制御とかでは、そんなに激しい通信は求められないことも 多々あります。単に機械の監視が目的なら100msec~200msecに1回通信 すればよい場合もあります すると、通信スレッドはこんな形になります   while (WaitForSingleObject(中止要求イベント, 100) != WAIT_OBJECT_0)   {      通信処理   }   前提として、"個別の通信を止める"ことはしないものとします。    止めるときは全て一斉に止めます。   個々の通信のエラー等で通信を止めたい場合は、スレッド制御関数から   returnしてください   ”中止要求イベント”は手動リセットイベントで実装します 自動にはしないでください   スレッド数に関係なく、イベントは1つで十分です   通信開始時にResetEventしてください   通信を終了したいときにSetEventします

nisecuroro
質問者

お礼

>前提として、"個別の通信を止める"ことはしないものとします。 >止めるときは全て一斉に止めます。 はい、一定時間経てば一斉に止めるようにしたいです。 >個々の通信のエラー等で通信を止めたい場合は、スレッド制御関数 >からreturnしてください それぞれのスレッドの個別の通信でタイムアウトを検出できれば returnさせれると思うのですが…CInternetSessionでのタイムアウトの指定方法、またタイムアウトの検出方法が分からないのです。 今はWinsocketで組み直しているところです。 >中止要求イベント 例えばWinSocketで実装したとして同期モードでrecv()させると そのwhileループはrecv()のところでブロックされてしまいますよね? 非同期でのやり方は調べてるのですが…まだよく分かってないです;;

  • yamaj_biz
  • ベストアンサー率71% (10/14)
回答No.1

コードをみるとワーカースレッドのようなので、メッセージを受け取る事が出来ません。(がんばれば出来ますが…) タイミングを取る場合は、イベントを使うのが手っ取り早いと思います。 また、強制終了させようとして出来ない事はないと思いますが、出来れば安全に終了させた方がいいと思います。 ワーカースレッドの場合、このコードの例でいけば「MyThreadProc」を抜けた時点でスレッドが削除されます。 pThread[i]->m_bAutoDelete = FALSE; として、自動削除しない設定にした上で、「pThread[i]->m_hThread」を集めた 「HANDLE hThread[HostNum]」を用意し、WaitForMultipleObjects 関数にて待ち合わせをするのが良いかと思われます。

nisecuroro
質問者

お礼

回答ありがとうございます。 最近帰宅したらすぐに寝てしまっていたので 返事が遅れてしまい申し訳ございません。 WaitForMultipleObjectsでスレッド自体を監視すれば良いのか… なんとなくイメージは沸いてきました。 (といってもスレッド自体よく理解してないですが)

関連するQ&A

  • スレッドを2つ作って1秒ごとに2つのスレッドが数値を表示するプログラム

    スレッドを2つ作って1秒ごとに2つのスレッドが数値を表示するプログラムを作りたいのですがうまくいきません。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> #include<pthread.h> void *threadMain(void *threadArgs); int main(void) { int i = 0; pthread_t threadID; for(i = 0;i < 2;i++){ pthread_create(&threadID,NULL,threadMain,(void *)NULL); } } void *threadMain(void *threadArgs) { int i = 0; while(1){ printf("%d\n",++i); sleep(1); } } 上記プログラムを実行すると1が2回表示されて終了してしまいます。 どこか間違えがあるのでしょうか。。

  • C++におけるスレッド制御に関して

    C++初心者です。 スレッド制御の勉強をしておりますが、 なかなかうまくいきません。 下記のソースのようにスレッド生成をしておりますが、 スレッド用メソッドには、*を付けて使用するしか方法はないのでしょうか? pthread_createに渡す第3パラメータをメソッド名のみにして、呼ばれ元のメソッドの戻り値をvoid* ではなく、void のみで実施したいと思っておりますが、方法がわかりません。 大変申し訳ございませんが、ご教授よろしくお願いいたします。 ############################################################## # pthread_test.cc ############################################################## #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> /* * スレッドパラメータ格納用 */ typedef struct {  char printVal;  int interval; } ThreadParamT; // スレッドイニシャル関数 void *ThreadTest(void *arg) {  ThreadParamT *thread_test_param =(ThreadParamT*)arg;  while(1) {   fprintf(stderr,"%c", thread_test_param->printVal);   sleep(thread_test_param->interval);  }  return NULL; } int main(int argc,char *argv[]) {  int status;  // スレッドのパラメータ  pthread_t thread_test;  ThreadParamT thread_test_param;  thread_test_param.printVal = 'a';  thread_test_param.interval = 1;  // スレッドを生成  status=pthread_create(&thread_test, NULL, ThreadTest, &thread_test_param);  if(status!=0){   fprintf(stderr,"ERR! OUT!\n");   exit(1);  }  // 10s間待つ  sleep(10);  fprintf(stderr, "\n");  return 0; } ##############################################################

  • スレッドの終了を知りたい(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; } ----プログラム(該当部分)ここまで----

  • スレッドとメッセージキューに関して

    現在、下記のようなプログラムを作成しています。 内容は、メッセージキューを受信するスレッドを生成するというイメージです。 処理内容は下記のようになります。  (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; } ----------------------------------------------------------------

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

    <プログラム環境> 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*/ ; } のようなスレッドを追加したいのですが全然出来ません。 宜しければご指摘お願い致します。

  • スレッドの作成について(pthread_create関数)

    以下のプログラムをLinuxで実行するとpthread_create関数の戻り値が『1』となり、errno変数には『4』が入ってしまいます。(どちらにも『0』が入っててほしい) 何がやりたいのかというと、子スレッドのプライオリティを優先指定にして、子スレッドが生成されることを確認したいだけなのですが。。。 (下のプログラムじゃきっと本質的には確認できたことにはならないとおもいますが。。。) 何故pthread_create関数の戻り値が『1』となり、errno変数には『4』が入ってしまうかわかる方、どなたかご教授願えませんでしょうか? -------------------------------ここから------------------------------- #include <pthread.h> #include <errno.h> void *test2( void * ); int main ( int argc, char **argv ) { int iThCreateRes=0; pthread_attr_t t_attr; int bRet=0; pthread_t szThreadHandle; errno = 0; pthread_attr_init( &t_attr ); pthread_attr_setdetachstate( &t_attr, PTHREAD_CREATE_JOINABLE ); pthread_attr_setschedpolicy( &t_attr,SCHED_RR ); pthread_attr_setinheritsched( &t_attr, PTHREAD_EXPLICIT_SCHED ); pthread_attr_setscope( &t_attr, PTHREAD_SCOPE_PROCESS ); iThCreateRes = pthread_create( &szThreadHandle, &t_attr, test2, (void *)777 ); if( iThCreateRes == 0 ) { } return ( bRet ); } void *test2( void *iParam ) { return (void*)0; } -------------------------------ここまで-------------------------------

  • [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()に変更すると ループを抜けるようなのですが、どうも納得できません。 上記のプログラムで問題、もしくはプロジェクトの 設定等に不備がある可能性がありましたら 御教授いただけたら幸いです。 よろしくおねがいいたします。

  • クラス内でのpthread_createに関して

    C言語初心者です。 下記のようなソースにて、クラス内でのスレッドを行うことが目的です。 しかし、下記のpthread_createにてコンパイルエラーとなります。 キャストエラーのようなのですが、キャスト方法がわかりません。 初歩的な質問で、大変申し訳御座いませんが、ご教授頂けませんでしょうか? ################################################################ #include <stdio.h> #include <pthread.h> // Testクラス class Test{ private: // スレッド処理 void testThread() { printf("### THREAD START ###\n"); return; } public: // スレッド開始 void threadStart() { // スレッド生成戻り値 int status; // スレッド pthread_t thread; // スレッド生成 status = pthread_create( &thread, NULL, (void*(*)(void*))testThread, NULL ); // スレッド生成結果 if ( status != 0 ) { printf("ERR!! pthread_create NG\n"); } return; } }; // メイン実行 int main(int argc, char *argv[]) { // Testクラスオブジェクト Test test; printf("### TEST START ###\n"); test.threadStart(); printf("### TEST E N D ###\n"); return 0; } ################################################################ 宜しくお願い致します。 以上です。

  • 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; } //================= 以上、宜しくお願いします。

  • 条件変数を用いた有限バッファ問題を考えています。

    皆さんこんにちは。 当方、プログラミングを勉強中の学生です。 条件変数を用いた有限バッファ問題を考えております。 以下に示すソースにおいて、関数produce()は1から1000までの整数を順に生成し、関数consume()はバッファから取り出した値の合計(1から1000までの和、500500となる)を求めるようプログラミングしているつもりなのですが、コンパイルして実行すると思ったような結果となりません。 どこが間違っているかご教授いただければ幸いです。 よろしくお願い致します。 以下、ソースとなります。 #include <stdio.h> #include <pthread.h> #define N 5 int buffer[N]; int inptr = 0, outptr = 0; int count = 0; int i = 0; int j = 0; int sum = 0; pthread_cond_t full = PTHREAD_COND_INITIALIZER; pthread_cond_t empty = PTHREAD_COND_INITIALIZER; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int produce (void) { i += 1; return i; } void consume (int x) { j += 1; sum += x; } void *producer(void *arg) { int data; for (;;) { if (i >= 1000) break; data = produce(); pthread_mutex_lock(&lock); while (count > N) pthread_cond_wait(&full, &lock); count = count + 1; buffer[inptr] = data; inptr = (inptr + 1) % N; pthread_mutex_unlock(&lock); pthread_cond_signal(&empty); } } void *consumer(void *arg) { int data; for (;;) { if (j >= 1000) break; pthread_mutex_lock(&lock); while (count == 0) pthread_cond_wait(&empty, &lock); count = count - 1; data = buffer[outptr]; outptr = (outptr + 1) % N; pthread_mutex_unlock(&lock); pthread_cond_signal(&full); consume(data); } } int main() { pthread_t a, b; pthread_create(&a, NULL, producer, NULL); pthread_create(&b, NULL, consumer, NULL); pthread_join(a, NULL); pthread_join(b, NULL); printf("sum = %d\n", sum); return 0; }