Передмова : Я шукаю пояснення, а не просто рішення. Я вже знаю рішення.
Незважаючи на те, що витратив кілька днів на вивчення статей MSDN про асинхронний візерунок на основі завдань (TAP), асинхронізуйте його та очікуйте, я все ще трохи розгублений щодо деяких тонких деталей.
Я пишу реєстратор для додатків Windows Store, і хочу підтримувати як асинхронний, так і синхронний журнал. Асинхронні методи слідують за 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 причиною замерзання? Чи є якась проблема з об’єктом завдання? Чи є неочевидний глухий кут?