Предисловие: я ищу объяснение, а не просто решение. Я уже знаю решение.
Несмотря на то, что я потратил несколько дней на изучение статей MSDN об асинхронном шаблоне на основе задач (TAP), асинхронности и ожидания, я все еще немного озадачен некоторыми деталями.
Я пишу регистратор для приложений Магазина Windows и хочу поддерживать как асинхронную, так и синхронную регистрацию. Асинхронные методы следуют за TAP, синхронные должны скрывать все это и выглядеть и работать как обычные методы.
Это основной метод асинхронного ведения журнала:
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);
}
Теперь соответствующий синхронный метод...
Версия 1:
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Wait();
}
Это выглядит правильно, но это не работает. Вся программа зависает навсегда.
Версия 2:
Хм.. Может задача не была запущена?
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.Start();
task.Wait();
}
Это вызывает InvalidOperationException: Start may not be called on a promise-style task.
Версия 3:
Хм.. Task.RunSynchronously
звучит многообещающе.
private void WriteToLog(string text)
{
Task task = WriteToLogAsync(text);
task.RunSynchronously();
}
Это вызывает InvalidOperationException: RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
Версия 4 (решение):
private void WriteToLog(string text)
{
var task = Task.Run(async () => { await WriteToLogAsync(text); });
task.Wait();
}
Это работает. Таким образом, 2 и 3 неправильные инструменты. А 1? Что не так с 1 и какая разница с 4? Что делает 1 причиной замораживания? Есть ли проблема с объектом задачи? Есть ли неочевидный тупик?