2008-10-31 15 views
113

Ein bisschen Probleme mit der Syntax, wo wir einen Delegaten anonym in einer Control.Invoke aufrufen möchten.Anonyme Methode in Aufruf aufrufen

Wir haben eine Reihe verschiedener Ansätze ausprobiert, alle ohne Erfolg.

Zum Beispiel:

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

wo someParameter dieser Methode lokal ist

Die oben wird in einem Compiler-Fehler führen:

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

Antwort

200

Da Invoke/BeginInvokeDelegate akzeptiert (anstelle eines typisierten Delegaten), müssen Sie den Compiler sagen, welche Art von Delegierten zu schaffen; MethodInvoker (2.0) oder Action (3.5) sind allgemeine Wahlmöglichkeiten (beachten Sie, dass sie die gleiche Signatur haben); etwa so:

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

Wenn Sie in Parameter übergeben müssen, dann „erfasst Variablen“ sind die Art und Weise:

string message = "Hi"; 
control.Invoke((MethodInvoker) delegate {this.Text = message;}); 

(Einschränkung: Sie ein bisschen vorsichtig sein müssen, wenn Aufnahmen mit async, aber Sync ist in Ordnung - dh die oben in Ordnung ist)

eine weitere Option ist eine Erweiterungsmethode zu schreiben:

public static void Invoke(this Control control, Action action) 
{ 
    control.Invoke((Delegate)action); 
} 

dann:

this.Invoke(delegate { this.Text = "hi"; }); 
// or since we are using C# 3.0 
this.Invoke(() => { this.Text = "hi"; }); 

Sie können natürlich das gleiche mit BeginInvoke:

public static void BeginInvoke(this Control control, Action action) 
{ 
    control.BeginInvoke((Delegate)action); 
} 

Wenn Sie nicht C# 3.0 verwenden, können Sie das gleiche mit einem regelmäßigen Instanzmethode tun könnte vermutlich in einer Form Basisklasse.

+0

Wie kann Ich übergebe Parameter an deine erste Lösung in dieser Antwort? Ich meinte diese Lösung: control.Invoke ((MethodInvoker) delegate {this.Text = "Hi";}); – uzay95

+1

Warum wird die Erweiterungsmethode aufgerufen, ohne dass eine explizite Umwandlung in Aktion ausgeführt werden muss? –

+0

Weil der Compiler daraus auf die Verwendung schließen kann. – RoboJ1M

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

Sie benötigen einen Delegierten erstellen Art. Das Schlüsselwort 'delegate' bei der anonymen Methodenerstellung ist ein bisschen irreführend. Sie erstellen keinen anonymen Delegaten, sondern eine anonyme Methode. Die von Ihnen erstellte Methode kann in einem Delegaten verwendet werden. Wie folgt aus:

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

Ich denke, das ist die richtige Antwort auf diese Frage sollte – electricalbah

42

Eigentlich müssen Sie Delegat-Schlüsselwort nicht verwenden. Nur passiert Lambda als Parameter:

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

ich Probleme mit den anderen Vorschlägen hatte, weil ich manchmal will Werte aus meinen Methoden zurückzukehren. Wenn Sie versuchen, MethodInvoker mit Rückgabewerten zu verwenden, scheint es nicht zu gefallen. Also ist die Lösung, die ich benutze, so (sehr glücklich, einen Weg zu hören, um dies prägnanter zu machen - ich benutze 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

Aus Gründen der Vollständigkeit kann dies auch über eine Aktion Methode/anonyme Methode Kombination erreicht werden:

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