Synchrones Warten auf eine asynchrone Operation und warum friert Wait () das Programm hier ein?
Vorwort: Ich suche eine Erklärung, nicht nur eine Lösung. Ich kenne die Lösung bereits.
Obwohl ich mehrere Tage mit dem Studium von MSDN-Artikeln über das aufgabenbasierte asynchrone Muster (TAP) verbracht habe, bin ich immer noch ein bisschen verwirrt über einige der feineren Details.
Ich schreibe einen Logger für Windows Store Apps und möchte sowohl die asynchrone als auch die synchrone Protokollierung unterstützen. Die asynchronen Methoden folgen dem TAP, die synchronen sollten dies alles verbergen und wie gewöhnliche Methoden aussehen und funktionieren.
Dies ist die Kernmethode der asynchronen Protokollierung:
private async Task WriteToLogAsync(string text)
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync("log.log",
CreationCollisionOption.OpenIfExists);
await FileIO.AppendTextAsync(file, text,
Windows.Storage.Streams.UnicodeEncoding.Utf8);
}
Nun die entsprechende Synchronmethode ...
Version 1:
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Wait();
}
Das sieht richtig aus, funktioniert aber nicht. Das ganze Programm friert für immer ein.
Version 2:
Hmm .. Vielleicht wurde die Aufgabe nicht gestartet?
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Start();
task.Wait();
}
Das wirftInvalidOperationException: Start may not be called on a promise-style task.
Version 3:
Hmm ..Task.RunSynchronously
hört sich gut an.
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.RunSynchronously();
}
Das wirftInvalidOperationException: RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
Version 4 (die Lösung):
private void WriteToLog(string text)
{
var task = Task.Run(async () => { await WriteToLogAsync(text); });
task.Wait();
}
Das funktioniert. 2 und 3 sind also die falschen Werkzeuge. Aber 1? Was ist los mit 1 und was ist der Unterschied zu 4? Was bewirkt, dass ich einfriere? Gibt es ein Problem mit dem Aufgabenobjekt? Gibt es einen nicht offensichtlichen Stillstand?