![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
親クラスウィンドウのボタンを押すと子クラスを作成して実行し、
子クラスは処理の経過や結果を親クラスに通知する、
というような処理をするために、下のようなコードを書きました。
(主要な部分のみの抜粋です。)
子クラスでは、親クラスへの通知後も引き続いて処理できるよう、
親クラスに対して非同期で通知したいため、
BeginInvoke を使用することにしました。
実行すると、「★A★」で親クラスに通知を実行した際、
・「★B★」は本来モーダルのはずが裏に回ってしまう
・「★C★」ではクロススレッド呼び出し方法の例外が発生
という問題が生じます。
BeginInvokeするとUIスレッドとは別のスレッドとしてChildEnventReceivedが呼ばれるためと解釈しています。(ほんとかな。)
こういったことをしたい場合、どうするのが普通でしょう?
下のコード自体はだいたい合っていて、
コントロールの操作は例えば「★C★」ではbtn.Invoke()するのが普通でしょうか?
とすると、そのためのdelegateやメッソドを定義しなければならず、
煩雑になりますね。
C++のPostMessageのようなことがやりたいだけなのですが。
C#は最近取り組み始めたばかりで、勉強中です。
普通はこうする、というような処理をご教授いただければ幸いです。
よろしくお願いします。
================================================
// 子クラスからの通知イベント
delegate void EventHandler();
public Parent
{
EventHandler handler;
private void btn_Click(object sender, EventArgs e)
{
btn.Enabled = false;
handler = new EventHandler(ChildEventReceived);
Child child = new Child();
child.SendEvent += hander;
child.Exec();
}
void ChildEnventReceived();
MessageBox.Show("Child State Received");
★B★このメッセージボックスが裏に隠れてしまう★B★
btn.Enabled = true;
★C★この操作は「有効でないスレッド間の操作」となる★C★
}
}
class Child
{
public event EventHandler SendEvent;
public void Exec()
{
★A★ここで親に対して通知する★A★
SendEvent.BeginInvoke(null, null);
}
}
================================================
A 回答 (1件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
using System;
using System.Threading;
using System.Windows.Forms;
delegate void EventHandler();
public class Parent:Form{
EventHandler handler;
Button btn;
public Parent(){
btn=new Button();
btn.Text="Exec";
btn.Click+=this.btn_Click;
Controls.Add(btn);
}
private void btn_Click(object sender, EventArgs e){
btn.Enabled = false;
// ★そもそも処理は UI スレッドではなく別スレッドでするのでは?★
// UIスレッドで処理をすると終わるまで Form が固まります。
// Form のメッセージを適宜処理する為に Application.DoEvents を Exec 内で定期的に呼び出す事もできますが、
// 同期的な実行になるので今回の非同期的に実行するという目的に適いません。
new Thread(new ThreadStart(()=>{
handler = new EventHandler(ChildEventReceived);
Child child = new Child();
child.SendEvent += handler;
child.Exec();
})).Start();
}
void ChildEventReceived(){
// ★Form.BeginInvoke を使えば、その Form の UI スレッド上で非同期的に実行される。★
this.BeginInvoke(new Action(()=>{
MessageBox.Show("Child State Received");
btn.Enabled = true;
}));
}
public static void Main(){
Application.Run(new Parent());
}
}
class Child{
public event EventHandler SendEvent;
public void Exec(){
Thread.Sleep(1000); // 重い処理など
// ★イベント自体の発火は同期で良いかと思います★
// 同期的に実行するかどうかは handler に任せた方が自然だと思います
if(SendEvent!=null)SendEvent();
}
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数内の変数に<summary>コメン...
-
C#でほかのファイルにある自作...
-
親クラスから子クラスへアクセス。
-
Java リフレクションについて
-
無名パッケージからのインポート
-
生成されたサーブレットのエラ...
-
キャストについて教えてください
-
クラス間でのデータ参照
-
範囲外の数値を代入したらエラ...
-
C# log4netの使い方
-
内部クラスのインスタンスを外...
-
違うクラスからの変数の共有化
-
C#のクラスライブラリでメッセ...
-
指定されたクラスの継承元の確...
-
下記のコードを実行すると、Mai...
-
c++,ある関数のクラスから別の...
-
JAVA、JAVA Scriptについて教え...
-
Java throwとthrowsの違いについて
-
変数名の付け方
-
エクセルVBAで、条件に一致する...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数内の変数に<summary>コメン...
-
クラス間でのデータ参照
-
C#にて別クラスの関数を使いたい
-
構造 他のクラスの構造体を別...
-
c++,ある関数のクラスから別の...
-
C#のクラスライブラリでメッセ...
-
C++でfriendクラスにしているの...
-
Java リフレクションについて
-
ひとつのファイルにクラスは1つ?
-
C#でほかのファイルにある自作...
-
範囲外の数値を代入したらエラ...
-
無名パッケージからのインポート
-
java-別クラスの変数の使い方を...
-
import と extends について
-
C# インターフェイスの実装
-
親クラスから子クラスへアクセス。
-
a href="..." とServlet
-
継承したクラス側のクラス名の取得
-
Java
-
JSPでbeanプロパティ(配列)を...
おすすめ情報