10月232007
0
参考:ControlクラスのInvokeメソッドで匿名メソッドを使うには?[2.0のみ、C#] − @IT
GUI描画とは別スレッドから、GUI要素を書き換える時
this.Invoke((MethodInvoker) delegate() { /* GUIの操作*/});
か
MethodInvoker func = delegate() { /*GUIの操作*/ };
this.Invoke(func);
でいい。
例えば
try{
this.Invoke((MethodInvoker)delegate(){textBoxMsg.Text+="hogehoge";});
}
catch(Exceptionex){
Console.Error.WriteLine(ex.Message);
}
とか。
GUIと別スレッドからGUI要素を書き換える時は(例えばSocket通信を受信するためにThreadを立てて回している時など)
Form.Invoke(Delegate)を使わないとデッドロックが起こってしまうのでC#2.0からは直接スレッド越えのメソッド呼び出しができなくなった。
これは1年ぐらい前に勉強して理解できた。
・s.h.log: C#のDelegateのカプセル化
・s.h.log: C#2.0 – PhidgetRFIDkitを使ってみる (あとDelegateとかInvokeとか)
でも毎度Delegateを使っていると、ちょっとGUI要素を変えたいだけなのにゴミのような関数が大量に必要になってしまう。そこでLLでよくやるように無名関数でInvoke()を実行したかった。
しかし、C#の無名関数(匿名メソッド)の宣言と実行の方法は
delegate d = delegate(){ /* 処理 */ }; // 宣言
Thread th = new Thread(d); // 登録
th.Start(); // 無名関数呼び出し
で、Threadから呼び出す。
参考:MSDN: 匿名メソッド (C#)
これだと、GUIスレッド外からGUI要素を書き換えられない。Thread.Start()ではなくControl.Invoke()を使わなければならない。
Control.Invoke()の引数であるDelegateは無名関数宣言のdelegateとは別の型で、直接キャストができない。
が、なぜかMethodInvoker型にするとできる。
よくわからないけどとにかく
this.Inovoke( (MethodInvoker) delegate(){ /* 処理 */ });
でいける事がわかってコードがすっきりした。