みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

[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でタイムアウトの使い方がよく分からない…、
もっとスマートな方法があれば教えていただきたいです。)

投稿日時 - 2009-08-17 16:28:00

QNo.5214447

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

WaitForSingleObjectを使っておられるようなので、WaitForMultipleObjectsを使って、終了用のイベントを追加してはいかがでしょう?

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

投稿日時 - 2009-08-21 22:53:19

ANo.2

基本的なことから述べます。
通信といっても色々あります。
例えば、インターネットに公開するファイルサーバーなどで、
何MByteもあるファイルをたくさんDLさせる場合などでしたら、
アクセスが集中した場合、CPUがパンクする恐れもありますので、
特殊な技術が必要です
(複数のサーバーに負荷分散するなど)

しかし、一般的な機械制御とかでは、そんなに激しい通信は求められないことも
多々あります。単に機械の監視が目的なら100msec~200msecに1回通信
すればよい場合もあります
すると、通信スレッドはこんな形になります
  while (WaitForSingleObject(中止要求イベント, 100) != WAIT_OBJECT_0)
  {
     通信処理

  }

  前提として、"個別の通信を止める"ことはしないものとします。
   止めるときは全て一斉に止めます。
  個々の通信のエラー等で通信を止めたい場合は、スレッド制御関数から
  returnしてください

  ”中止要求イベント”は手動リセットイベントで実装します
自動にはしないでください
  スレッド数に関係なく、イベントは1つで十分です
  通信開始時にResetEventしてください
  通信を終了したいときにSetEventします

投稿日時 - 2009-08-19 23:00:00

お礼

>前提として、"個別の通信を止める"ことはしないものとします。
>止めるときは全て一斉に止めます。
はい、一定時間経てば一斉に止めるようにしたいです。

>個々の通信のエラー等で通信を止めたい場合は、スレッド制御関数
>からreturnしてください
それぞれのスレッドの個別の通信でタイムアウトを検出できれば
returnさせれると思うのですが…CInternetSessionでのタイムアウトの指定方法、またタイムアウトの検出方法が分からないのです。
今はWinsocketで組み直しているところです。

>中止要求イベント
例えばWinSocketで実装したとして同期モードでrecv()させると
そのwhileループはrecv()のところでブロックされてしまいますよね?
非同期でのやり方は調べてるのですが…まだよく分かってないです;;

投稿日時 - 2009-08-20 23:55:32

ANo.1

コードをみるとワーカースレッドのようなので、メッセージを受け取る事が出来ません。(がんばれば出来ますが…)
タイミングを取る場合は、イベントを使うのが手っ取り早いと思います。
また、強制終了させようとして出来ない事はないと思いますが、出来れば安全に終了させた方がいいと思います。

ワーカースレッドの場合、このコードの例でいけば「MyThreadProc」を抜けた時点でスレッドが削除されます。

pThread[i]->m_bAutoDelete = FALSE;

として、自動削除しない設定にした上で、「pThread[i]->m_hThread」を集めた 「HANDLE hThread[HostNum]」を用意し、WaitForMultipleObjects 関数にて待ち合わせをするのが良いかと思われます。

投稿日時 - 2009-08-18 17:44:20

お礼

回答ありがとうございます。
最近帰宅したらすぐに寝てしまっていたので
返事が遅れてしまい申し訳ございません。

WaitForMultipleObjectsでスレッド自体を監視すれば良いのか…
なんとなくイメージは沸いてきました。
(といってもスレッド自体よく理解してないですが)

投稿日時 - 2009-08-20 23:31:24

あなたにオススメの質問