ぴぐノート

Good code is its own best documentation.

C/C++ MFC プログラミング言語

【MFC】マルチスレッドでプログレスバーを実装しよう その2

投稿日:

昨日に続き、プログレスバーをマルチスレッドを用いて実装してみましょう。
作成の目的は、

  • スレッド実行中はモーダルダイアログを表示させること。
  • モーダルダイアログではプログレスバーを表示し進捗が分かること。
  • 実行中のスレッドはダイアログのメンバーにアクセスできること。
  • スレッド処理が完了次第、モーダルダイアログを閉じること。

でした。
昨日までで関数宣言などは完了したので、各関数の定義・実装を進めていきます。

関連リンク: 【MFC】マルチスレッドでプログレスバーを実装しよう その1

{プロジェクト名}Dlg.cpp

まずはメインダイアログであるDIALOG1のソースコードを編集していきます。

静的変数 static int nCountの実装

プログレスバーが表示されるダイアログから監視される変数として、

を宣言していました。
静的変数なので実装が必要です。
{プロジェクト名}Dlg.cppファイルの適当な場所に以下の実装を記述します。

クラス名は適宜読み替えてくださいね。

ボタンのイベントハンドラ、OnBnClickedButton1()の実装

次に前回、メインダイアログ(DIALOG1)に追加したボタンのイベントハンドラ、OnBnClickedButton1()の実装を行いましょう。

機能としてはボタンを押下されたらスレッドを開始し、プログレスバーが表示されるダイアログを表示します。

AfxBeginThread()関数がスレッドを開始する関数になります。

関連リンク:AfxBeginThread | MSDN

第6引数まである関数ですが、第3~第6まではデフォルト引数が指定されているので、2つの引数を渡します。

  • 第一引数:別スレッドとして実行される関数のポインタ
    (ワーカースレッドの制御関数)
  • 第二引数:制御関数に渡す引数

第二引数はvoid *型なのでポインタであれば何でも渡すことができます。
今回は制御関数の中でメインダイアログクラスのメンバー関数を呼び出すため、自分自身を引数として渡しています。

5行目 ~ 6行目はダイアログのクラスを宣言し、DoModal()関数を呼び出すことでプログレスバー付きのダイアログ(DIALOG2)を表示させています。
メインダイアログの処理はDIALOG2に移りましたので、DIALOG2のウィンドウを閉じるまではここで処理が止まります

スレッドの処理が完了次第、DIALOG2は終了するように実装するため、処理が戻る8行目に完了を通知するメッセージボックスを表示します。

ワーカースレッドの制御関数
static UINT ThreadProc(LPVOID pParam)

AfxBeginThread()関数から呼び出される、ワーカースレッドの制御関数は以下のように実装します。

まずは、AfxBeginThread()の第二引数に与えたvoid *型を正しい型(今回はダイアログクラスでした)に変換します

関連リンク:reinterpret_cast 演算子 | MSDN
関連リンク:dynamic_cast 演算子 | MSDN

まず、reinterpret_castでポインタ型の変換、dynamic_castで正しいオブジェクトへと変換します。

正しく変換が完了できれば、実際に別スレッドで実行される関数を呼び出します。
基本的には重たい処理やユーザーを待たせたい処理の実行関数になるでしょうか。

実処理を行う関数、void ThreadProc()

この実処理を行う関数は人によってそれぞれ異なるのでどんな内容でも構わないのですが、以下のようにしました。

メンバー変数である、nCount(今回は静的変数ですがメンバー変数であってもアクセス可能です)をインクリメントし、100回に一度、100ミリ秒のスリープを実行します。
nCountが10,000,000に到達した時点でループから抜けて処理が終了、スレッドもほぼ同時に終了となります。

ここまででメインのダイアログの記述は終了です。
長くなってしまったのでプログレスバーが表示されるダイアログクラスの実装は明日行いましょう。

まとめ

スレッドが目にも止まらぬ速度で終わってはスレッドの進行が分からないので無意味なスリープなどを挿入していますが、実際にはファイルの書き出しやローディングなどが実行されることになるでしょうか。

クラスの設計をしっかり行っていればメインのダイアログで処理に必要な変数はできる限り少なくしておくべきですがコントロール変数などを持っているダイアログのメンバーにアクセスできるため、利用しやすいですよね。

スポンサーリンク

スポンサーリンク

-C/C++, MFC, プログラミング言語

執筆者:

関連記事

Eclipse NeonとCDT/MinGWでC++開発環境を作成しよう!(2)

前回の記事でEclipseにCDTを追加インストールすることができました。 今回はMinGWとMSYSをインストールし、Eclipse上でC++プロジェクトを実行してみましょう。 この際に必要なダウン …

【OpenCV】OpenCVを使ってみよう!表示・回転・拡縮・二値化

前回インストールを行ったOpenCVライブラリを使ってサンプルプログラムをいくつか作成してみましょう。 OpenCVはすごく有名な画像処理ライブラリなのでインターネットで探せばサンプルプログラムはたく …

【Boost】オープンソースライブラリBoostをインストールしよう

普段からC++でのプログラムを作成していてBoost(ブースト)を知らないという人はあまり多くないかもしれませんが、「実はまだ使ったことない…」という人もいるのではないでしょうか? ライブ …

【MFC】フォルダー選択ダイアログの表示【Visual C++】

出力先の指定などフォルダー選択のダイアログを表示させたいことがあります。 フォルダー選択ダイアログを表示させるためには、SHBrowseForFolder関数を使います。 SHBrowseForFol …

C++でインターフェイスを作成しよう。

私事ですが今後業務ではC++を使用することになりそうです。 今まではウェブ関連の業務であったり、ちょっとしたテスト程度だったのでJavaを中心に使っていたため、C++の文法など少し忘れ気味です&#82 …