2008-10-31 62 views
113

对于我们想要在Control.Invoke中匿名调用委托的语法有点麻烦。Invoke调用中的匿名方法

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

例如:

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

其中someParameter是本地的这种方法

以上将导致一个编译器错误:

Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type

回答

200

因为Invoke/BeginInvoke接受Delegate(而不是一个类型的代表),你需要告诉编译器什么类型的委托创建的; (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基类。

+0

怎样才能我在这个答案中传递参数给你的第一个解决方案?我的意思是这个解决方案:control.Invoke((MethodInvoker)delegate {this.Text =“Hi”;}); – uzay95 2009-11-26 14:05:56

13
myControl.Invoke(new MethodInvoker(delegate() {...})) 
13

你需要创建一个委托类型。匿名方法创建中的关键字'委托'有点令人误解。您不是创建匿名委托,而是创建匿名方法。您创建的方法可用于委托中。就像这样:

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

我想这应该是正确的回答这个问题 – electricalbah 2013-07-08 08:10:22

42

其实你不需要使用委托关键字。只是通过lambda作为参数:

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

我有其他建议的问题,因为我想有时从我的方法返回值。如果您尝试使用带有返回值的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; 
     })); 
    } 
7

为了完整起见,这也可以通过一个操作方法/匿名方法的组合来实现:

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