Ich habe irgendwo gehört, dass das asynchrone Warten auf C # 5 so großartig sein wird, dass Sie sich darüber keine Sorgen machen müssen:
if (InvokeRequired)
{
BeginInvoke(...);
return;
}
// do your stuff here
Es sieht so aus, als würde der Rückruf einer Warteoperation im ursprünglichen Thread des Aufrufers erfolgen. Mehrfach wurde von Eric Lippert und Anders Hejlsberg festgestellt, dass diese Funktion darauf zurückzuführen ist, dass Benutzeroberflächen (insbesondere Benutzeroberflächen für Touchscreens) schneller reagieren müssen.
Ich denke, eine übliche Verwendung eines solchen Features wäre etwa so:
public class Form1 : Form
{
// ...
async void GetFurtherInfo()
{
var temperature = await GetCurrentTemperatureAsync();
label1.Text = temperature;
}
}
Wenn nur ein Rückruf verwendet wird, löst das Festlegen des Bezeichnungstextes eine Ausnahme aus, da er nicht im Thread der Benutzeroberfläche ausgeführt wird.
Bisher konnte ich keine Ressource finden, die dies bestätigt. Weiß jemand davon? Gibt es Dokumente, die technisch erklären, wie dies funktioniert?
Bitte geben Sie einen Link von einer zuverlässigen Quelle an, antworten Sie nicht einfach mit "Ja".
quelle
await
Bezug auf die Funktionalität höchst unwahrscheinlich . Es ist nur eine Menge syntaktischer Zucker für die Weitergabe . Möglicherweise gibt es noch einige andere Verbesserungen an WinForms, die helfen sollen? Dies würde jedoch unter das .NET-Framework fallen und nicht unter C #.Antworten:
Ich glaube, Sie werden hier ein paar Dinge durcheinander bringen. Was Sie für Fragen ist bereits möglich , mit
System.Threading.Tasks
demasync
undawait
in C # 5 werden nur für die gleiche Funktion einen wenig schöner syntaktischen Zucker zu liefern.Lassen Sie uns ein Winforms-Beispiel verwenden - fügen Sie eine Schaltfläche und ein Textfeld in das Formular ein und verwenden Sie diesen Code:
Führen Sie es aus und Sie werden sehen, dass (a) es den UI-Thread nicht blockiert und (b) Sie nicht die übliche Fehlermeldung "Cross-Thread-Operation ungültig" erhalten - es sei denn, Sie entfernen das
TaskScheduler
Argument aus dem letztenContinueWith
, in Welchen Fall wirst du.Dies ist ein moorhafter Fortführungsstil . Die Magie geschieht in der
TaskScheduler
Klasse und speziell in der Instanz, die von abgerufen wirdFromCurrentSynchronizationContext
. Übergeben Sie dies an eine beliebige Fortsetzung, und geben Sie an, dass die Fortsetzung auf dem Thread ausgeführt werden muss, der dieFromCurrentSynchronizationContext
Methode aufgerufen hat - in diesem Fall auf dem UI-Thread.Kellner sind etwas anspruchsvoller in dem Sinne, dass sie wissen, auf welchem Thread sie begonnen haben und auf welchem Thread die Fortsetzung stattfinden muss. So kann der obige Code etwas natürlicher geschrieben werden:
Diese beiden sollten sehr ähnlich aussehen, und tatsächlich sind sie sich sehr ähnlich. Die
DelayedAddAsync
Methode gibt jetzt einTask<int>
statt eines zurückint
, und daher werdenawait
nur die Fortsetzungen auf jede dieser Methoden angewendet. Der Hauptunterschied besteht darin, dass der Synchronisierungskontext in jeder Zeile weitergegeben wird, sodass Sie dies nicht explizit wie im letzten Beispiel ausführen müssen.Theoretisch sind die Unterschiede viel bedeutender. Im zweiten Beispiel
button1_Click
wird tatsächlich jede einzelne Zeile in der Methode im UI-Thread ausgeführt, aber die Task selbst (DelayedAddAsync
) wird im Hintergrund ausgeführt. Im ersten Beispiel läuft alles im Hintergrund , mit Ausnahme der Zuweisung,textBox1.Text
die wir explizit dem Synchronisationskontext des UI-Threads zugeordnet haben.Das ist es, was wirklich interessant ist
await
- die Tatsache, dass ein Kellner in der Lage ist, auf dieselbe Weise ein- und auszuspringen , ohne Anrufe zu blockieren. Sie rufenawait
, den aktuellen Thread Nachrichten an die Verarbeitung geht zurück, und wenn es fertig ist, wird die Erwartenden genau abholen, wo sie aufgehört hat , im selben Thread aufhörte es in. Aber in Bezug auf IhreInvoke
/BeginInvoke
Kontrast in der Frage, I‘ Es tut mir leid zu sagen, dass Sie das schon vor langer Zeit aufgeben sollten.quelle
ArrayList
Klasse in neuem Code verwenden. Ich selbst habe noch kaum Erfahrung mit RX. Die Menschen lernen, was sie wissen müssen, und teilen, was sie bereits wissen, auch wenn das, was sie bereits wissen, nicht mehr aktuell ist. Diese Antwort könnte in einigen Jahren veraltet sein.Ja, für den UI-Thread wird der Rückruf einer Warteoperation für den ursprünglichen Thread des Aufrufers ausgeführt.
Eric Lippert hat vor einem Jahr eine 8-teilige Serie darüber geschrieben: Fabulous Adventures In Coding
EDIT: und hier ist Anders '// build / presentation: channel9
Übrigens, hast du bemerkt, dass wenn du "// build /" auf den Kopf stellst, du "/ plinq //" bekommst?
quelle
Jon Skeet hielt eine hervorragende Präsentation über Async-Methoden in C # 5, die Sie möglicherweise als äußerst nützlich erachten:
http://skillsmatter.com/podcast/home/async-methods
quelle