ぴぐノート

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

執筆者:

関連記事

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

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

【MFC入門】ツリーコントロールでフォルダ内のファイルを表示しよう【Visual C++】

エクスプローラーのディレクトリー構成などツリーコントロールの活用場面は多いです。 ドラッグアンドドロップされたフォルダーに格納されている、フォルダー/ファイルを表示できれば、どのファイルにアクセスする …

【Visual C++】フルパスを指定してフォルダー階層を作成する。

MFCなどでファイル走査などのプログラミングを行っていると、D&D(ドラッグアンドドロップ)されたフォルダー内の全ファイル(サブフォルダー含め)に何か処理を行い、同じような階層を維持したまま別 …

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

前回の記事でXMLファイルの書き込みは難しくなくできそうでしたネ。 今回はXMLファイルの書き込みを行い、出力してみましょう。 読み込みと同じくライブラリファイルは不要で、ヘッダーファイルのみで利用で …

【MFC入門】ダイアログにファイルをドラッグアンドドロップしよう【Visual C++】

ファイル操作を行うツールなどを作成する際には、ファイルをドラッグアンドドロップできると便利です。 ファイルがどこにあるか分からない場合などは参照させることも多いと思いますが、プログラムやファイルの検証 …