Prenez la méthode System.Windows.Forms.Control.Invoke (méthode Delegate)
Pourquoi cela donne-t-il une erreur de compilation:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Pourtant, cela fonctionne bien:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Quand la méthode attend un délégué simple?
Invoke(()=>DoStuff)
et j'ai toujours eu l'erreur. Le problème était que j'utilisais le «ceci» implicite. Pour le faire fonctionner à partir d'un membre de contrôle , vous devez être explicite:this.Invoke(()=>DoStuff)
.Fatigué de lancer des lambdas encore et encore?
la source
Lambda<T>
classe a une méthode de conversion d'identité appeléeCast
, qui renvoie tout ce qui est passé (Func<T, T>
). Maintenant , laLambda<T>
est déclarée comme ceLambda<Func<int, string>>
qui signifie que si vous passez unFunc<int, string>
à laCast
méthode, elle retourne enFunc<int, string>
arrière, carT
dans ce casFunc<int, string>
.Neuf dixièmes du temps, les gens obtiennent cela parce qu'ils essaient de se rassembler sur le thread d'interface utilisateur. Voici la manière paresseuse:
Maintenant qu'il est tapé, le problème disparaît (réponse de qv Skeet) et nous avons cette syntaxe très succincte:
Pour les points bonus, voici une autre astuce. Vous ne le feriez pas pour les éléments de l'interface utilisateur, mais dans les cas où vous avez besoin de SomeMethod pour bloquer jusqu'à ce qu'il se termine (par exemple, E / S de demande / réponse, en attente de la réponse), utilisez un WaitHandle (qv msdn WaitAll, WaitAny, WaitOne).
Notez que AutoResetEvent est un dérivé WaitHandle.
Et un dernier conseil car les choses peuvent s'emmêler: WaitHandles bloque le fil. C'est ce qu'ils sont censés faire. Si vous essayez de marshaler sur le thread d'interface utilisateur pendant qu'il est bloqué , votre application se bloque . Dans ce cas (a) une refactorisation sérieuse est en ordre, et (b) en tant que hack temporaire, vous pouvez attendre comme ceci:
la source
System.Windows.Threading.Dispatcher.CurrentDispatcher
retournera le répartiteur du thread ACTUEL - c'est-à-dire que si vous appelez cette méthode à partir d'un thread qui n'est pas le thread d'interface utilisateur, le code ne sera pas exécuté sur le thread d'interface utilisateur.Peter Wone. tu es un homme. En poussant un peu plus loin votre concept, j'ai proposé ces deux fonctions.
Je place ces deux fonctions dans mon application Form, et je peux passer des appels à partir de travailleurs en arrière-plan comme celui-ci
Peut-être un peu paresseux, mais je n'ai pas besoin de configurer les fonctions des travailleurs, ce qui est très pratique dans des cas comme celui-ci
Essentiellement, obtenez des adresses IP à partir d'une interface graphique DataGridView, envoyez-leur un ping, définissez les icônes résultantes sur vert ou rouge et réactivez les boutons du formulaire. Oui, c'est un "parallel.for" dans un backgroundworker. Oui, c'est BEAUCOUP de surcharge, mais c'est négligeable pour les listes courtes et le code beaucoup plus compact.
la source
J'ai essayé de me baser sur la réponse de @Andrey Naumov . C'est peut-être une légère amélioration.
Où le paramètre type
S
est le paramètre formel (le paramètre d'entrée, qui est au minimum requis pour déduire le reste des types). Maintenant, vous pouvez l'appeler comme:Vous pouvez avoir des surcharges supplémentaires pour
Action<S>
etExpression<Action<S>>
de la même manière dans la même classe. Pour les autres types intégrés de délégués et d' expression, vous devrez écrire des classes séparées commeLambda
,Lambda<S, T>
,Lambda<S, T, U>
etc.Avantage de cela, je vois sur l'approche originale:
Une spécification de type en moins (seul le paramètre formel doit être spécifié).
Ce qui vous donne la liberté de l'utiliser contre n'importe quel
Func<int, T>
, pas seulement quandT
c'est-à-direstring
, comme le montrent les exemples.Prend en charge les expressions immédiatement. Dans l'approche précédente, vous devrez spécifier à nouveau les types, comme:
pour les expressions.
L'extension de la classe pour d'autres types de délégués (et d'expressions) est également fastidieuse, comme ci-dessus.
Dans mon approche, vous ne devez déclarer les types qu'une seule fois (cela aussi un de moins pour
Func
s).Une autre façon de mettre en œuvre la réponse d'Andrey est de ne pas devenir complètement générique
Les choses se réduisent donc à:
C'est encore moins de taper, mais vous perdez certains types de sécurité, et à mon avis, cela n'en vaut pas la peine.
la source
Un peu tard à la fête mais vous pouvez aussi lancer comme ça
la source
la source
Jouer avec XUnit et les assertions Fluent il était possible d'utiliser cette capacité en ligne d'une manière que je trouve vraiment cool.
Avant
Après
la source