Answers:
因为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;});
(注意:如果使用captures async,则需要谨慎一点,但是sync很好-即上述情况很好)
另一种选择是编写扩展方法:
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())
为了完整起见,这也可以通过Action方法/匿名方法的组合来完成:
//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;
}));
}
我喜欢用Action代替MethodInvoker,它更短并且看起来更干净。
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) { }
}
}