2009-06-09 21 views
14

Cerco di capire perché un metodo BeginInvoke non accetta un metodo anonimo.Metodi anonimi e delegati

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    if (InvokeRequired) 
    { 
     //Won't compile 
     BeginInvoke(delegate(object sender, ProgressChangedEventArgs e) 
     { bgWorker_ProgressChanged(sender, e); }); 
    } 

    progressBar1.Increment(e.ProgressPercentage); 
} 

Mi dice 'non può convertire da 'metodo anonimo' a 'System.Delegate', mentre quando ho lanciato il metodo anonimo a un delegato che funziona?

BeginInvoke((progressDelegate)delegate { bgWorker_ProgressChanged(sender, e); }); 
+1

Date un'occhiata a questa domanda, anche: http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call – tanascius

risposta

7

La classe Delegate è la classe base per i tipi di delegati. Tuttavia, solo il sistema e i compilatori possono derivare esplicitamente dalla classe Delegate o dalla classe MulticastDelegate. Non è inoltre consentito derivare un nuovo tipo da un tipo delegato. La classe Delegate non è considerata un tipo delegato; è una classe utilizzata per derivare tipi delegati. Source - MSDN

Di qui la necessità del cast esplicito su un tipo derivato da delegato. Si verificherà questo particolare errore del compilatore quando si passa un metodo anonimo per un parametro di tipo System.Delegate - fortunatamente si tratta di uno scenario raro. Questa è solo troppa flessibilità.

delegate void MyDelegate(); 

    static void DoSomething_Flexible(Delegate d) 
    { d.DynamicInvoke();  } 
    static void DoSomething_Usable(MyDelegate d) 
    { d();  } 
    static void Main(string[] args) 
    { 
    // requires explicit cast else compile error Error "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type  
    DoSomething_Flexible((MyDelegate) delegate { Console.WriteLine("Flexible is here!"); }); 

    // Parameter Type is a .NET Delegate, no explicit cast needed here. 
    DoSomething_Usable(delegate { Console.WriteLine("Usable is here!"); }); 
    } 

Ulteriori informazioni su questo a this page by Ian Griffith. (Vedi le paras dopo l'intestazione Note)

+0

Risposta piacevole, ma non sono sicuro di descrivere SomeControl.BeginInvoke (metodo Delegate, oggetto param [] args) come * raro *. –

+0

@PeterWone - :). Suggerirei di utilizzare un'istanza di BackgroundWorker per gestire l'affinità del thread UI. Non puoi fare nulla sui metodi esistenti di terze parti scritti in questo modo: devi contrassegnare con una piccola (azione) cast – Gishu

16

È necessario dire al compilatore cosa tipo di delegato per creare, dal momento che Invoke (ecc) basta prendere Delegate (piuttosto che qualcosa di più specifico).

da applicare al più vasto pubblico, MethodInvoker è un pratico tipo delegato

BeginInvoke((MethodInvoker) delegate(...) {...}); 

Tuttavia ... BackgroundWorker.ProgressChanged incendi sul thread UI automaticamente - in modo che non hanno nemmeno bisogno di questo.

5

La maggior parte delle volte si ha a che fare con un delegato senza parametri o con un predicato in questi casi. Il modo più semplice di ordinare questo è il casting del metodo anonimo direttamente su Action o Predicate rispettivamente; semplicemente non è necessario creare un tipo di delegato personalizzato per cose semplici come quella.

Così avrete qualcosa come

BeginInvoke((Action)delegate(){YourCode.DoSomething();}); 

o

BeginInvoke((Predicate)delegate(object yourParameter){return YourCode.IsTheParameterSomething(yourParameter)}); 

HTH

Problemi correlati