Invoke调用中的匿名方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Invoke调用中的匿名方法相关的知识,希望对你有一定的参考价值。
我们想要在Control.Invoke中匿名调用委托的语法有点麻烦。
我们已经尝试了许多不同的方法,但都无济于事。
例如:
myControl.Invoke(delegate() { MyMethod(this, new MyEventArgs(someParameter)); });
其中someParameter是此方法的本地方法
以上将导致编译器错误:
无法将匿名方法转换为类型'System.Delegate',因为它不是委托类型
因为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;});
(告诫:如果使用捕获异步,你需要有点谨慎,但同步很好 - 即上面没问题)
另一种选择是编写扩展方法:
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
基类中。
实际上你不需要使用delegate关键字。只需将lambda作为参数传递:
control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));
myControl.Invoke(new MethodInvoker(delegate() {...}))
您需要创建委托类型。匿名方法创建中的关键字“委托”有点误导。您不是创建匿名委托,而是匿名方法。您创建的方法可以在委托中使用。像这样:
myControl.Invoke(new MethodInvoker(delegate() { (MyMethod(this, new MyEventArgs(someParameter)); }));
为了完整起见,这也可以通过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();
});
我有其他建议的问题,因为我想有时从我的方法返回值。如果您尝试使用带有返回值的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;
}));
}
我从来不明白为什么这会对编译器产生影响,但这已经足够了。
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) { }
}
}
以上是关于Invoke调用中的匿名方法的主要内容,如果未能解决你的问题,请参考以下文章