プロが教える店舗&オフィスのセキュリティ対策術

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クラスのプロテクト変数を内部で操作しています。

A 回答 (1件)

時間のかかる処理というのがループして実行するようなタイプの処理だと、マルチスレッド使わなくても以下のような方法で簡単にできます。

時間のかかる処理の中で、キャンセルボタンは普通押せません。それは1メッセージの処理の中で長~い処理を行っているからです。それならば、メッセージ処理中にも別のメッセージを処理できる仕組みを作ってやればいいのです。

○ Before
for(int loop=0; loop < 1000000; loop ++) {
 // ここで時間のかかる処理実行
}

この場合だとループがすべて終了するまで待たされます。


○ After
for(int loop=0; loop < 1000000; loop ++) {

 // ここで時間のかかる処理

 MSG msg;
 while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
 if(!AfxGetApp()->PumpMessage())
 {
  ::PostQuitMessage(0);
  break;
 }
}

ループ1回に付きメッセージ処理を行うため、処理中であっても例えば中断ボタン操作などが普通に処理できます。
    • good
    • 1
この回答へのお礼

ご回答ありがとうございます。

上記のやり方を試したところ、上手く1つのスレッドで処理中の中断が実現できました。ありがとうございました。

ところで、1つのスレッドでキャンセルボタン付ダイアログの表示と処理を並行すると、PCのスペックにも依存すると思いますが、ダイアログのレスポンスがマルチスレッドに比べて遅い気がします。(処理中にダイアログボックスをドラッグ移動しようとすると、多少カクカクします)。もし、呼出し元で画面表示をするスレッドと処理をするスレッド間で、キャンセルボタンの押下判定をするには、スレッド間通信を行うしかないんですかねぇ。

お礼日時:2005/05/10 10:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています