ぴぐノート

Good code is its own best documentation.

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

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

投稿日:

プログレスバーをマルチスレッドを用いた実装について最後の記事です。
引き続き作成の目的は、

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

でした。
今回はプログレスバーが表示されるダイアログ(DIALOG2)の実装を確認します。
こちらはスレッド呼び出しなどはないため、簡単な内容になっています。

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

PrgDlg.cpp

最初の記事でOnInitDialog関数、WindowProc関数をそれぞれオーバーロードしました。
OnInitDialog関数で進行状況バーの下限/上限を設定します。
次にWindowProc関数でプログレスバーの現在位置を設定します。

WindowProc関数はダイアログにメッセージが発行されると呼ばれるため、頻繁に呼ばれる関数です。
実際に運用する場合は定期的に呼ばれるような関数を定義するといいかもしれません。

OnInitDialog関数

コントロール変数m_PrgCtrl(CProgressCtrl型)のSetRange関数でプログレスバーの下限/上限を設定します。
今回はマジックナンバーで【10,000,000】と記載していますが、定数を利用したり、ファイル走査などであれば総ファイル数を指定するなどが考えられます。

関連リンク:CProgressCtrl クラス | MSDN
関連リンク:CProgressCtrl::SetRange | MSDN

WindowProc関数

WindowProc関数ではウィンドウハンドルが作成されていれば、OnInitDialog関数で設定した上限と別スレッドでインクリメントされ続けているカウンター変数を比較し、まだ上限に達していなければ進行状況バーを更新します。

既に上限に達している場合はWM_CLOSEをポストし、ダイアログを閉じるように指示しています。

ウィンドウハンドルが作成されているかどうかの確認をしない場合は、実行時エラーが表示されます。これはWindowProc関数内で比較などをしているためです。

関連リンク:WindowProc 関数 | MSDN
関連リンク:CProgressCtrl::SetPos | MSDN

さて、これでようやく完成です。
実行してみると確かに少しずつプログレスバーがカウンタの値によって増加されているのが分かるかと思います。

multithread-progress_005
multithread-progress_006

問題点

さて、これまでの流れでプログレスバーをマルチスレッドで実装することはできました。
ですが、各所で見られたように問題点も多いです。

  • スレッドで実行する処理が、プログレスバーを表示するダイアログ作成前に完了する。
    → 例えば、void ThreadProc(void)を何も処理しないようにするとダイアログ生成よりも早くスレッドが閉じられ意図しない動作になるでしょう。

他にもマジックナンバーを埋め込んでいたり、色々問題点がありました。
こういった点をスマートに解決するためにはやはりVisual C++などの書籍を購入し、セマフォなども含めて学習の必要がありそうです。

まとめ

短いプログラムでしたがスレッドの生成について確認してみました。
今回紹介した方法は【ワーカースレッド】を用いた方法で実装しました。

実際に運用する場合には専用の関数を用意するなど、より堅牢なプログラムを行う必要がありそうです。

スポンサーリンク

スポンサーリンク

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

執筆者:

関連記事

C++のプリプロセッサの復習をしよう その1

C++を勉強していた時期から苦手だったのがプリプロセッサでした。 インクルートガードに#ifndefやら#defineやら#pragma onceやら…。 C++に限った話ではありませんが …

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

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

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

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

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

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

【OpenCV】MFCのピクチャーコントロールに描画しよう!

前回、OpenCVを使って画像の回転や二値化などを行って動作確認をしました。 今回はMFCでダイアログベースのアプリケーションを作成し、ピクチャーコントロールにOpenCVで読み込んだ画像を表示させて …