调用中的匿名方法

我们想在 Control.Invoke 中匿名调用委托的语法有点问题。

我们尝试了许多不同的方法,但都无济于事。

例如:

myControl.Invoke(delegate() { MyMethod(this, new MyEventArgs(someParameter)); });

这个方法的哪个参数是本地的

以上操作将导致编译器错误:

无法将匿名方法转换为“ System.Committee”类型,因为它不是委托类型

137926 次浏览
myControl.Invoke(new MethodInvoker(delegate() {...}))

您需要创建一个委托类型。匿名方法创建中的关键字“ committee”有点误导人。您创建的不是匿名委托,而是匿名方法。您创建的方法可以在委托中使用。像这样:

myControl.Invoke(new MethodInvoker(delegate() { (MyMethod(this, new MyEventArgs(someParameter)); }));

因为 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基类中。

实际上,您不需要使用 committee 关键字。只需将 lambda 作为参数传递:

control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));

我对其他建议有问题,因为我有时想从我的方法返回值。如果您尝试使用 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 方法/匿名方法的组合来实现:

//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();
});

我一直不明白为什么这对编译器有影响,但这就足够了。

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) { }
}
}

我喜欢用 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";
}