AfxBeginThreadの強制終了

[戻る]
ジュビロ 2004/01/29(木) 15:59:45
開発環境はVC++6.0 OS2000 MFCです。
スレッドの勉強を始めたばかりのものです、過去ログを拝見しましたが分かりませんでしたので
投稿させて頂きました。

OnStartボタンで1000までカウントを行なうスレッドを実行します。
OnStopボタンでカウント1000が終了するまでにスレッドを止めたいのですが
下記のソースでは終了できませんでした。
何が行けないのでしょうか?宜しくお願い致します。

void CThreadDlg::OnStart() {
 m_SrThreadStatus = AfxBeginThread((AFX_THREADPROC)Thread1, (LPVOID) 
 this,THREAD_PRIORITY_NORMAL);
}
void CThreadDlg::OnStop() 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    if(m_SrThreadStatus){
        SrThreadEvent.SetEvent();
    }
}

UINT Thread1(LPVOID pvParam)
{
    CThreadDlg *pDlg = (CThreadDlg*)pvParam;

    char lpszStr[64];
    int i=0; /* カウンタ変数クリア */

    while (i<1000) { /* 1000までカウント */

    i++; /* カウンタを一つ増やす */

    wsprintf(lpszStr,"Thread1 %8d",i);    
    pDlg->m_edit.SetWindowText(lpszStr); /* カウンタの数を表示 */
    
    Sleep(1); /* ウエイト */
    }

    return(0);
}

ひろぴー 2004/01/29(木) 16:46:22
> void CThreadDlg::OnStop() 
> {
>     // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
>     if(m_SrThreadStatus){
>         SrThreadEvent.SetEvent();
>     }
> }

SrThreadEventの定義はどうなっていますか?

dairygoods 2004/01/29(木) 21:03:14
スレッド側にSrThreadEventがセットされたら処理を終了する
というコードがありませんけど…

ジュビロ 2004/01/30(金) 08:54:00
SrThreadEventはヘッダーにてCEvent SrThreadEvent;と宣言しております。
勘違いをしておりましてSrThreadEvent.SetEvent();
で終了するものばかり思っておりました。
WaitForSingleObjectを解除する処理だとわかりました。

OnStop関数を修正しなくてなりません。
調べておりますが、ちょっと出口がみつからないのですが…
お手数掛けます。

ひろぴー 2004/01/30(金) 09:00:31
>    while (i<1000) { /* 1000までカウント */
>
>    i++; /* カウンタを一つ増やす */
>
>    wsprintf(lpszStr,"Thread1 %8d",i);    
>    pDlg->m_edit.SetWindowText(lpszStr); /* カウンタの数を表示 */
>    
>    Sleep(1); /* ウエイト */
>    }
上記ループ内でCThreadDlgのメンバ変数を参照(中断判定用を新規に作成)し、値によってルー
プを抜ける処理を入れるのがよいかと思います。

ジュビロ 2004/01/30(金) 09:25:57
皆さんすみません、質問内容は違いますが
同じソースでのマルチポストをしてしまいました。
以後、同じ繰り返しをしませんので宜しくお願い致します。

ジュビロ 2004/01/30(金) 09:44:59
WaitForSingleObjectが入ったソースですが以下のように修正して
終了するようになりました。
m_Thread1Stopはint型で作成しました。
こんな終了の仕方でいいのか心配です。ソース的に綺麗なのか、一般的な終了の仕方があるのか
アドバイス頂けませんか?

void CThreadDlg::OnStop() 
{
   m_Thread1Stop = 1;
   if(m_SrThreadStatus){
     SrThreadEvent.SetEvent();
   }
}

UINT Thread1(LPVOID pvParam)
{
  CThreadDlg *pDlg = (CThreadDlg*)pvParam;

  char lpszStr[64];
  int i=0; /* カウンタ変数クリア */

  while (i<1000) { /* 1000までカウント */
    if(pDlg->m_Thread1Stop == NULL){
    i++; /* カウンタを一つ増やす */

    wsprintf(lpszStr,"Thread1 %8d",i);    
    pDlg->m_edit.SetWindowText(lpszStr); /* カウンタの数を表示 */
    
    WaitForSingleObject(pDlg->SrThreadEvent, 100);
    
    Sleep(1); /* ウエイト */
  }else{
    pDlg->m_SrThreadStatus = NULL;
    return(0);
  }
}

ひろぴー 2004/01/30(金) 10:47:56
m_Thread1Stopはpublicですから、他からも制御出来てしまいますのでprivateメンバにしま
す。
その場合Thread1()関数からはアクセス出来なくなるのでThread1()もCThreadDlgクラスのメン
バ関数とし、staticにしてあげればOKですね。
m_Thread1Stopもstaticにします。

OnOk()等のダイアログを終了する関数にもm_Thread1Stopの値をセットするようにします。
で、WaitForSingleObject()でスレッド処理が終了するまで待つ。
WaitForSingleObject()の使い方が違うくないですか?
別の用途でやっているならいいのですが。

>    pDlg->m_SrThreadStatus = NULL;
>    return(0);
この手の処理は個人的にはループの外で行うようにします。
ループはブレイクで抜けています。
その辺は好みの問題なので、1例を挙げたまでという事で。

ジュビロ 2004/01/30(金) 11:27:56
[[解決]]
基礎不足ですみません。
>m_Thread1Stopもstaticにします。

今は
初期はNULL
OnStopで1
Thread1を抜ける時はNULL
の流れですが、staticにすることで何がかわるのですか?

επιστημη [E-Mail] [HomePage] 2004/01/30(金) 11:32:20
> staticにすることで何がかわるのですか?

何故本を読まないんだろう…

ジュビロ 2004/01/30(金) 13:06:21
投げやり質問大変失礼しました。
1つずつ調べたいと思います。

m_Thread1StopをプライベートにすることでThread1()関数からはアクセス出来なくなるので
Thread1()もCThreadDlgクラスのメンバ関数とし、staticにするとありますが
分からなかったので本を見ましたがかかれておりません。

お手数ですがNETなどで調べたいと思いますのでキーワードなど教えて頂けたらと思います。

ひろぴー 2004/01/30(金) 13:32:17
検索するキーワードではないですが、
・なぜThread1()をメンバにする際にstaticとしなければならないのか?
は納得出来ているでしょうか?
その辺から検索してもひっかかるかもしれません。

なぜm_Thread1Stopをstaticにしなければならないのか?と思ったら、staticにしないでコン
パイルするのも手です。その辺でもピンと来るかもしれないですし。

スレッド処理とは直接関係ない基本的な事なので、επιστημηさんは何故本を読まないんだろ
う…と言われたのだと思います。

とおり 2004/01/30(金) 13:45:19
相変わらずですね…

>m_Thread1StopをプライベートにすることでThread1()関数からはアクセス出来なくなるので
>Thread1()もCThreadDlgクラスのメンバ関数とし、staticにするとありますが
>分からなかったので本を見ましたがかかれておりません。

上記文章のうちの「どこが」分からないのですか?
「全部」というのはなしですよ。あなたは、人が言った(書いた)ことをそのまま書き並べた
だけです。そもそもそういう態度が、自分で努力をしていないと思われる(事実?)わけですが。

ジュビロ 2004/01/30(金) 15:57:37
間違っていたら指摘して下さい。
>なぜThread1()をメンバにする際にstaticとしなければならないのか?
m_Thread1Stopを静的変数にするとm_Thread1Stopを処理する為に
Thread1()もstaticをつけ静的メンバ関数(静的メンバ関数は静的データメンバしか扱わない為)としな
くてはならない。

>m_Thread1Stopはpublicですから、他からも制御出来てしまいますのでprivateメンバにしま
>す。
これはクラス内で共通する変数を持たせたいからprivateで隠蔽化させる為

とここまで解釈をしておりますが・・・。

ひろぴー 2004/01/30(金) 16:24:00
> m_Thread1Stopを静的変数にするとm_Thread1Stopを処理する為に
> Thread1()もstaticをつけ静的メンバ関数(静的メンバ関数は静的データメンバしか扱わない
> 為)としな
> くてはならない。
う”惜しい。逆です。
Thread1()をstaticにする必要があるからm_Thread1Stopもstaticにしないとアクセス出来な
い為です。

> これはクラス内で共通する変数を持たせたいからprivateで隠蔽化させる為
隠蔽化する為、privateのクラスメンバとした訳ですね。

tetrapod 2004/01/30(金) 17:03:03
エー、必ずしもスレッド関数本体は static である必然は無いのです。
入り口だけ static になればOK。
こーいう場合のイディオムは以下のとおりです。

class threaded_class {
  static int Thread_Entry(void* p) {
    return static_cast<theaded_class*>(p)->Thread_Function();
  }
  int Thread_Function(void) { ... }
};
当然スレッドを起動するときに渡すパラメータは this となる、っと。

古いスレッドには追加発言できません。