2008-10-31 12 views
113

Tener un problema con la sintaxis en la que queremos llamar a un delegado de forma anónima dentro de Control.Invoke.Método anónimo en Invoke call

Hemos intentado una serie de enfoques diferentes, todo fue en vano.

Por ejemplo:

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

donde someParameter es local en este método

Lo anterior dará lugar a un error de compilación:

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

Respuesta

200

Debido Invoke/BeginInvoke acepta Delegate (en lugar de un delegado mecanografiado), es necesario indicar al compilador qué tipo de delegado para crear; MethodInvoker (2.0) o Action (3.5) son opciones comunes (tenga en cuenta que tienen la misma firma); de este modo:

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

Si tiene que pasar en los parámetros, las "variables capturados" son, pues, el camino:

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

(advertencia: tiene que ser un poco prudente si se utiliza capturas asíncrono , pero sincronización está bien - es decir, la anterior es bien)

Otra opción es escribir un método de extensión:

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

a continuación:

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

Por supuesto, puede hacer lo mismo con BeginInvoke:

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

Si no puede utilizar C# 3.0, se podría hacer lo mismo con un método de instancia regulares , presumiblemente en una clase base Form.

+0

¿Cómo puede Paso parámetros a su primera solución en esta respuesta? Quise decir esta solución: control.Invoke ((MethodInvoker) delegate {this.Text = "Hi";}); – uzay95

+1

¿Por qué se invoca el método de extensión sin tener que realizar un lanzamiento explícito a la acción? –

+0

Porque el compilador puede inferir eso del uso. – RoboJ1M

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

Es necesario crear un delegado tipo. La palabra clave 'delegar' en la creación de métodos anónimos es un poco engañosa. No está creando un delegado anónimo, sino un método anónimo. El método que creó se puede usar en un delegado. De esta manera:

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

creo que esto debería ser la respuesta correcta a esta pregunta – electricalbah

42

En realidad no es necesario utilizar la palabra clave delegar. Sólo tiene que pasar lambda como parámetro:

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

he tenido problemas con las otras sugerencias porque quiero devolver valores a veces de mis métodos. Si intenta utilizar MethodInvoker con valores devueltos, parece que no le gusta. Entonces la solución que uso es así (muy feliz de escuchar una manera de hacer esto más breve, estoy usando 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

En aras de la exhaustividad, esto también se puede lograr a través de un método de acción combinación método/anónima:

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