回答:
Invoke
/ BeginInvoke
はDelegate
(型付きデリゲートではなく)受け入れるので、作成するデリゲートのタイプをコンパイラーに通知する必要があります。MethodInvoker
(2.0)またはAction
(3.5)が一般的な選択肢です(同じ署名があることに注意してください)。そのようです:
control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});
パラメータを渡す必要がある場合は、「キャプチャされた変数」がその方法です。
string message = "Hi";
control.Invoke((MethodInvoker) delegate {this.Text = message;});
(注意:キャプチャasyncを使用する場合は少し注意する必要がありますが、同期は問題ありません。つまり、上記は問題ありません)
別のオプションは拡張メソッドを書くことです:
public static void Invoke(this Control control, Action action)
{
control.Invoke((Delegate)action);
}
次に:
this.Invoke(delegate { this.Text = "hi"; });
// or since we are using C# 3.0
this.Invoke(() => { this.Text = "hi"; });
もちろん、同じことをBeginInvoke
次のように行うこともできます。
public static void BeginInvoke(this Control control, Action action)
{
control.BeginInvoke((Delegate)action);
}
C#3.0を使用できない場合は、通常のインスタンスメソッドを使用して、おそらくForm
基本クラスで同じことができます。
Form.Load += Loader()
古いものの代わりにできることと同じですForm.Load += new EventHandler(Loader())
実際には、デリゲートキーワードを使用する必要はありません。パラメータとしてラムダを渡すだけです:
control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));
完全を期すために、これはアクションメソッド/匿名メソッドの組み合わせを介して実行することもできます。
//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
SomeFunc();
SomeOtherFunc();
});
Invoke((Action) Process);
最良の答えです、ありがとう!
メソッドから値を返す場合があるため、他の提案に問題がありました。MethodInvokerを戻り値で使用しようとすると、気に入らないようです。だから私が使用する解決策は次のようなものです(これをもっと簡潔にする方法を聞いてとても嬉しいです-私はc#.net 2.0を使用しています):
// Create delegates for the different return types needed.
private delegate void VoidDelegate();
private delegate Boolean ReturnBooleanDelegate();
private delegate Hashtable ReturnHashtableDelegate();
// Now use the delegates and the delegate() keyword to create
// an anonymous method as required
// Here a case where there's no value returned:
public void SetTitle(string title)
{
myWindow.Invoke(new VoidDelegate(delegate()
{
myWindow.Text = title;
}));
}
// Here's an example of a value being returned
public Hashtable CurrentlyLoadedDocs()
{
return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
{
return myWindow.CurrentlyLoadedDocs;
}));
}
MethodInvokerの代わりにActionを使用したいのですが、短くてすっきりしています。
Invoke((Action)(() => {
DoSomething();
}));
// OR
Invoke((Action)delegate {
DoSomething();
});
例えば。
// Thread-safe update on a form control
public void DisplayResult(string text){
if (txtResult.InvokeRequired){
txtResult.Invoke((Action)delegate {
DisplayResult(text);
});
return;
}
txtResult.Text += text + "\r\n";
}
なぜこれがコンパイラに影響を与えるのか理解できませんでしたが、これで十分です。
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
control.Invoke(action);
}
}
おまけ:Control.Invoke
バックグラウンドスレッドから使用している場合、コントロールのテキスト/進行状況/有効な状態を更新していて、コントロールが既に破棄されているかどうかは気にしない可能性が高いため、いくつかのエラー処理を追加します。
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
try
{
if (!control.IsDisposed) control.Invoke(action);
}
catch (ObjectDisposedException) { }
}
}