Prefazione : sto cercando una spiegazione, non solo una soluzione. Conosco già la soluzione.
Nonostante abbia trascorso diversi giorni a studiare articoli MSDN sul Task-based Asynchronous Pattern (TAP), asincrono e attendo, sono ancora un po 'confuso su alcuni dei dettagli più fini.
Sto scrivendo un logger per le app di Windows Store e voglio supportare la registrazione sia asincrona che sincrona. I metodi asincroni seguono il TAP, quelli sincroni dovrebbero nascondere tutto ciò e apparire e funzionare come metodi ordinari.
Questo è il metodo principale di registrazione asincrona:
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);
}
Ora il corrispondente metodo sincrono ...
Versione 1 :
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Wait();
}
Sembra corretto, ma non funziona. L'intero programma si blocca per sempre.
Versione 2 :
Hmm .. Forse l'attività non è stata avviata?
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Start();
task.Wait();
}
Questo genera InvalidOperationException: Start may not be called on a promise-style task.
Versione 3:
Hmm .. Task.RunSynchronously
sembra promettente.
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.RunSynchronously();
}
Questo genera InvalidOperationException: RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
Versione 4 (la soluzione):
private void WriteToLog(string text)
{
var task = Task.Run(async () => { await WriteToLogAsync(text); });
task.Wait();
}
Questo funziona Quindi, 2 e 3 sono gli strumenti sbagliati. Ma 1? Cosa c'è di sbagliato in 1 e qual è la differenza con 4? Cosa fa 1 causare un congelamento? C'è qualche problema con l'oggetto task? C'è un deadlock non ovvio?