ぴぐノート

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, プログラミング言語

執筆者:

関連記事

【OpenCV】OpenCVをビルドして画像処理をしてみよう!

今日はOpenCVを使って画像表示をしてみたいと思います。 ツールやアプリケーションを作る場合、多かれ少なかれ画像処理は必要になってくるのではないでしょうか。 また画像処理関係ではまると泥沼化する場合 …

【MFC入門】メッセージボックスにエラーコードを表示させよう

ライブラリなどを使用していると、戻り値にエラーコードを返す関数は比較的多いです。 GetLastError関数(最新のエラーコードを取得する関数)がライブラリに含まれていることもありますが、そうでない …

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

実は今回紹介する方法は、もしかしたら正しくないのかもしれません。 ダイアログベースのプログラムで以下の条件を満たし、プログレスバーを表示したいと考えました。 スレッド実行中はモーダルダイアログを表示さ …

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

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

【Boost】boost::property_treeでXMLファイルを読み込もう!

以前はアプリケーションの設定ファイルに単純なテキストである、INIファイルを用いていたアプリケーションも多かったですが、最近はXML(Extensible Markup Language:拡張可能なマ …