- ベストアンサー
C#スレッドから親ウィンドウへの通知の方法は?
- C#でスレッドから親ウィンドウへの通知を行う方法について説明します。
- MFC C++ではWinPostMessageを使用していましたが、C#ではイベントを使用することが一般的です。
- イベントを使用する場合、通知を受け取る側は非同期になり、一連の処理を終えるまで復帰しません。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
基本的にはThreadクラスでどうとでもなるし、Formのボタンクリックによるイベントハンドラがスレッドを起動するのであればBackgroundWorkerが中間スレッドになるのが良いかも。以下、画面の描画やマウスボタンクリックの処理をしているスレッドをUIスレッド、複数のスレッドを起動して終了を待ち、最後にUIスレッドに報告するスレッドを子スレッド、何かしらの処理をする複数のスレッドを孫スレッドとして説明する。 BackgroundWorkerクラスを使う時の流れ ・BackgroundWorkerのインスタンスを作る ・Startボタンクリックイベント→BackgroundWorker#RunWorkerAsyncを呼び出すのとStartをDisable、EndをEnableにするのをやる(*1)。 ・BackgroundWorker#DoWorkイベント→今ここは子スレッドで動いている。ここで複数の孫スレッドを起動し、全ての孫スレッドの終了を待ってからDoWorkイベントを終了する。孫スレッドから子スレッドへなんらかの通知をしたい時にはdelegateなどを用いてコールバックすれば良い。 ・子スレッドで動作するDoWorkが終了すると自動的にUIスレッドでBackgroundWorker#RunWorkerCompletedイベントが呼ばれる(*3)のでボタンのEnable/Disableを切り替える(*2)。 ・EndボタンクリックイベントではBackgroundWorker#CancelAsyncを呼び出す。子スレッドで動いているDoWorkの中ではBackgroundWorker#CancellationPendingがtrueなら孫スレッドに停止命令を出すなどする。 ・DoWorkを動かしている子スレッドから画面に何か通知したい時はBackgroundWorker#ReportProgressを呼び出し、UIスレッドではBackgroundWorker#ProgressChangedイベントに応答して画面にメッセージ出すなどする。 (*3)があなたのイメージと少し違うかも知れないが、複数のスレッドがメインスレッドに対してそれぞれ起動と終了を通知するのではなく、単純にががっとスレッドたちを起動して全部が終わるのをざざっと待って全部が終わったら自動的に親が終了を判断できるという方がシンプルになるんじゃないかな。
お礼
回答をありがとうございます。 まだC#を始めたばかりで、正直ちょっとややこしいな、という印象がありましたが、 よく読めば、ああなるほどと、大変参考になりました。 いろいろとWebで調べてみたのですが、PostMessage のようなことは BeginInvoke で、 という書き込みが散見されました。 そちらのやり方にも興味があり、Delegate の BeginInvoke も調べてみて、それ自体 はなんとなく分かったのですが、どうやれば PostMessage の代替になるのかまでは分 かりません。 また、その件でも質問してみようかと考えているところです。 もしご存知でしたら、またヒントをいただけると、大変ありがたいです。 今回は勉強になりました。 ありがとうございました。