2009-06-09 8 views
14

J'essaie de comprendre pourquoi une méthode BeginInvoke n'accepte pas une méthode anonyme.Méthodes et délégués anonymes

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

Il me dit « ne peut pas convertir « méthode anonyme » à « System.Delegate » tandis que quand je jetai la méthode anonyme à un délégué, il ne fonctionne?

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

Jetez un oeil à cette question aussi: http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call – tanascius

Répondre

7

La classe Delegate est la classe de base pour les types de délégué. Cependant, seuls le système et les compilateurs peuvent dériver explicitement de la classe Delegate ou de la classe MulticastDelegate. Il est également interdit de dériver un nouveau type à partir d'un type de délégué. La classe Delegate n'est pas considérée comme un type de délégué; C'est une classe utilisée pour dériver des types de délégués. Source - MSDN

D'où la nécessité de la conversion explicite en un type dérivé de délégué. Vous rencontrez cette erreur de compilation particulière lorsque vous passez une méthode anonyme pour un paramètre de type System.Delegate - heureusement, il s'agit d'un scénario rare. C'est trop de flexibilité.

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!"); }); 
    } 

Plus d'informations à ce sujet à this page by Ian Griffith. (Voir les paragraphes après l'en-tête Notes)

+0

Bonne réponse, mais je ne suis pas sûr de décrire SomeControl.BeginInvoke (méthode Delegate, param object [] args) comme * rare *. –

+0

@PeterWone - :). Je suggère d'utiliser une instance BackgroundWorker pour gérer l'affinité Thread UI. Vous ne pouvez rien faire à propos des méthodes tierces existantes écrites de cette manière - vous devez marquer avec une petite distribution (Action) – Gishu

16

Vous devez dire au compilateur de type de délégué pour créer, depuis Invoke (etc) juste prendre Delegate (plutôt que quelque chose de plus spécifique).

Pour appliquer au plus grand public, MethodInvoker est un type délégué pratique

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

Mais ... BackgroundWorker.ProgressChanged feux sur le thread d'interface utilisateur automatiquement - donc vous ne même pas besoin de cela.

5

La plupart du temps, vous avez affaire à un délégué sans paramètre ou à un prédicat dans ces cas-là. Le moyen le plus simple de trier ceci est de lancer votre méthode anonyme directement sur Action ou Predicate respectivement; vous n'avez simplement pas besoin de créer un type de délégué personnalisé pour des choses simples comme ça.

Ainsi, vous aurez quelque chose comme

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

ou

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

HTH

Questions connexes