2008-10-31 179 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(); 
});