2012-12-12 7 views
5

Ich schaue auf die neuen async und await Schlüsselwörter in C# und versuche nur, ein Gefühl für sie zu bekommen.FileStream WriteAsync und warten auf Verwirrung

Ich bin auf der MSDN FileStream.WriteAsync()example, und ich war mir nicht sicher, ob ich etwas verstanden habe.

Das Beispiel ist wie folgt:

using System; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.IO; 

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private async void Button_Click(object sender, RoutedEventArgs e) 
     { 
      UnicodeEncoding uniencoding = new UnicodeEncoding(); 
      string filename = @"c:\Users\exampleuser\Documents\userinputlog.txt"; 

      byte[] result = uniencoding.GetBytes(UserInput.Text); 

      using (FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate)) 
      { 
       SourceStream.Seek(0, SeekOrigin.End); 
       await SourceStream.WriteAsync(result, 0, result.Length); 
      } 
     } 
    } 
} 

Was ich nicht bekommen, die Platzierung der await ist. Es scheint, dass Sie das Element Task, das von WriteAsync() zurückgegeben wird, nicht nehmen kann, da dies immer zu einem Syntaxfehler führt. Der einzige Weg, wie ich das kompilieren könnte, ist, den await mit dem Anruf zu verlassen.

Aber wenn Sie dies tun, wartet es nicht auf den Anruf zu beenden? Dies macht es nicht sehr asynchron ...

+0

Was meinst du mit "nimm" den "Task" Gegenstand? –

+0

@Jon Etwas wie 'Task t = SourceStream.WriteAsync (Ergebnis, 0, result.Length);' und später '' erwarten t; ' – Andrew

+2

Sie können das auf jeden Fall tun - was lässt Sie denken, Sie können nicht? –

Antwort

13

Ich vermute, das Problem ist mit Ihrem Verständnis, was await tut.

Aber wenn Sie dies tun, wartet es nicht auf den Anruf zu beenden? Dies macht es nicht sehr asynchron ...

Wenn Sie await etwas, Sie „Block asynchron“ - Ihre asynchrone Funktion wird fortgesetzt, wenn der asynchrone Vorgang abgeschlossen ist, aber die unmittelbare Anruf wird abgeschlossen sofort.

In diesem Fall wird der UI-Thread entsperrt, da Button_Click zurückkehrt, aber wenn der Dateischreibvorgang abgeschlossen ist, wird die Ausführung (noch im UI-Thread) an das Ende des Ausdrucks await zurückgegeben ... Sie werden schließe dann die FileStream und schließe die asynchrone Funktion ab.

Es wäre klarer, was los war, wenn Sie etwas anderes nach Ausdruck (z. B. Aktualisierung der UI) await Ausdruck. Aber ja, es ist wirklich ist asynchron - es ermöglicht Ihnen nur, Code zu schreiben, der aussieht synchron.

+0

Also lassen Sie uns sagen, ich habe eine Methode 'doWork()' nach dem 'warten', die Methode würde nicht aufgerufen werden bis NACH dem Schreibvorgang? – Andrew

+3

@Andrew: In der Tat.Aber während Ihre asynchrone Funktion darauf gewartet hat, würde * sie den UI-Thread nicht halten. Es ist, als würde man eine Pizza bestellen - man kann die Pizza erst essen, wenn sie geliefert wurde, aber man kann auch andere Dinge tun :) –

+0

Ich denke, das macht Sinn. Vielen Dank! – Andrew

1

Das Warten blockiert nicht, während es wartet. Was passiert, ist, dass der Compiler einige komplexe Dinge erledigt, um nach dem Warten eine so genannte Fortsetzung des gesamten Codes zu machen, und die Aufgabe anweist, diese Fortsetzung auszuführen, wenn sie abgeschlossen ist.

Grundsätzlich sind die letzten Zeilen des Button_Click Verfahren sind übersetzt:

FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate); 
SourceStream.Seek(0, SeekOrigin.End); 
Task t = SourceStream.WriteAsync(result, 0, result.Length); 
t.ContinueWith(_ => SourceStream.Dispose()); 

Natürlich ist dies vereinfacht wird, da dies effizienter ausgeführt werden, wenn die WriteAsync sofort beendet, zum Beispiel.