Prefácio : estou procurando uma explicação, não apenas uma solução. Eu já conheço a solução.
Apesar de ter passado vários dias estudando artigos do MSDN sobre o padrão assíncrono baseado em tarefas (TAP), assíncrono e aguardando, ainda estou um pouco confuso sobre alguns dos detalhes.
Estou escrevendo um criador de logs para os aplicativos da Windows Store e quero oferecer suporte ao registro assíncrono e síncrono. Os métodos assíncronos seguem a TAP, os síncronos devem esconder tudo isso e parecer e funcionar como métodos comuns.
Este é o método principal de log assíncrono:
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);
}
Agora, o método síncrono correspondente ...
Versão 1 :
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Wait();
}
Parece correto, mas não funciona. Todo o programa congela para sempre.
Versão 2 :
Hmm .. Talvez a tarefa não tenha sido iniciada?
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Start();
task.Wait();
}
Isso joga InvalidOperationException: Start may not be called on a promise-style task.
Versão 3:
Hmm ... Task.RunSynchronously
parece promissor.
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.RunSynchronously();
}
Isso joga InvalidOperationException: RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
Versão 4 (a solução):
private void WriteToLog(string text)
{
var task = Task.Run(async () => { await WriteToLogAsync(text); });
task.Wait();
}
Isso funciona. Então, 2 e 3 são as ferramentas erradas. Mas 1? O que há de errado com 1 e qual é a diferença para 4? O que faz 1 causar um congelamento? Há algum problema com o objeto de tarefa? Existe um impasse não óbvio?