Nehmen Sie die Methode System.Windows.Forms.Control.Invoke (Delegate-Methode)
Warum führt dies zu einem Fehler bei der Kompilierung:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Dies funktioniert jedoch gut:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Wann erwartet die Methode einen einfachen Delegaten?
Invoke(()=>DoStuff)
den Fehler zu erhalten. Das Problem war, dass ich das implizite 'dies' verwendet habe. Damit es in einem Control-Mitglied funktioniert, müssen Sie Folgendes angeben :this.Invoke(()=>DoStuff)
.Sind Sie es leid, immer wieder Lambdas zu werfen?
quelle
Lambda<T>
Klasse über eine Identitätskonvertierungsmethode namensCast
, die alles zurückgibt, was übergeben wird (Func<T, T>
). Jetzt wird dasLambda<T>
als deklariert.Lambda<Func<int, string>>
Wenn Sie eineFunc<int, string>
to-Cast
Methode übergeben, wird esFunc<int, string>
zurückgegeben, da diesT
in diesem Fall der Fall istFunc<int, string>
.Neun Zehntel der Fälle erhalten die Benutzer dies, weil sie versuchen, auf dem UI-Thread zu marshallen. Hier ist der faule Weg:
Jetzt, da es getippt ist, verschwindet das Problem (siehe Skeets Antwort) und wir haben diese sehr prägnante Syntax:
Für Bonuspunkte hier ein weiterer Tipp. Sie würden dies nicht für UI-Inhalte tun, aber in Fällen, in denen SomeMethod bis zum Abschluss blockiert werden muss (z. B. Anforderungs- / Antwort-E / A, Warten auf die Antwort), verwenden Sie ein WaitHandle (siehe msdn WaitAll, WaitAny, WaitOne).
Beachten Sie, dass AutoResetEvent eine WaitHandle-Ableitung ist.
Und ein letzter Tipp, weil sich die Dinge verheddern können: WaitHandles blockieren den Faden. Das sollen sie tun. Wenn Sie versuchen, auf dem UI-Thread zu marshallen , während Sie ihn blockiert haben , bleibt Ihre App hängen. In diesem Fall (a) ist ein ernsthaftes Refactoring angebracht, und (b) als vorübergehender Hack können Sie folgendermaßen warten:
quelle
System.Windows.Threading.Dispatcher.CurrentDispatcher
gibt den Dispatcher des CURRENT-Threads zurück. Wenn Sie diese Methode von einem Thread aufrufen, der nicht der UI-Thread ist, wird der Code nicht auf dem UI-Thread ausgeführt.Peter Wone. Du bist ein Mann. Ich habe Ihr Konzept etwas weiterentwickelt und mir diese beiden Funktionen ausgedacht.
Ich platziere diese beiden Funktionen in meiner Formular-App und kann Anrufe von solchen Hintergrundmitarbeitern tätigen
Vielleicht ein bisschen faul, aber ich muss keine Worker-Doed-Funktionen einrichten, was in solchen Fällen sehr praktisch ist
Rufen Sie im Wesentlichen einige IP-Adressen von einer GUI-DataGridView ab, pingen Sie sie an, setzen Sie die resultierenden Symbole auf Grün oder Rot und aktivieren Sie die Schaltflächen im Formular erneut. Ja, es ist ein "parallel.for" in einem Hintergrundarbeiter. Ja, es ist eine Menge Aufruf von Overhead, aber es ist vernachlässigbar für kurze Listen und viel kompakteren Code.
quelle
Ich habe versucht, dies auf der Antwort von @Andrey Naumov aufzubauen . Möglicherweise ist dies eine leichte Verbesserung.
Dabei
S
ist der Typparameter der formale Parameter (der Eingabeparameter, der mindestens erforderlich ist, um auf den Rest der Typen zu schließen). Jetzt können Sie es so nennen:Sie können zusätzliche Überladungen für
Action<S>
undExpression<Action<S>>
in derselben Klasse haben. Für andere in Delegaten und Ausdrucksarten gebaut, werden Sie separate Klassen gerne schreiben müssenLambda
,Lambda<S, T>
,Lambda<S, T, U>
usw.Vorteil davon sehe ich gegenüber dem ursprünglichen Ansatz:
Eine Typspezifikation weniger (nur der formale Parameter muss angegeben werden).
Dies gibt Ihnen die Freiheit, es gegen jeden zu verwenden
Func<int, T>
, nicht nur wennT
es gesagt wirdstring
, wie in Beispielen gezeigt.Unterstützt Ausdrücke sofort. Bei dem früheren Ansatz müssen Sie erneut Typen angeben, z.
für Ausdrücke.
Das Erweitern der Klasse für andere Delegatentypen (und Ausdruckstypen) ist ähnlich umständlich wie oben.
In meinem Ansatz müssen Sie Typen nur einmal deklarieren (das auch eins weniger für
Func
s).Eine andere Möglichkeit, Andreys Antwort umzusetzen, besteht darin, nicht vollständig generisch zu werden
Die Dinge reduzieren sich also auf:
Das ist noch weniger Tippen, aber Sie verlieren bestimmte Typensicherheit, und imo, das ist es nicht wert.
quelle
Etwas spät zur Party, aber du kannst auch so besetzen
quelle
quelle
Beim Spielen mit XUnit und Fluent Assertions war es möglich, diese Inline-Funktion auf eine Weise zu nutzen, die ich wirklich cool finde.
Vor
Nach dem
quelle