Preface:
I'm looking for an explanation, not just a solution. I already know the
solution.
Despite having spent several days
studying MSDN articles about the Task-based Asynchronous Pattern (TAP), async and await,
I'm still a bit confused about some of the finer
details.
I'm writing a logger for Windows Store
Apps, and I want to support both asynchronous and synchronous logging. The asynchronous
methods follow the TAP, the synchronous ones should hide all this, and look and work
like ordinary methods.
This is the core method
of asynchronous
logging:
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);
}
Now
the corresponding synchronous
method...
Version
1:
private void
WriteToLog(string text)
{
Task task =
WriteToLogAsync(text);
task.Wait();
}
This
looks correct, but it does not work. The whole program freezes
forever.
Version
2:
Hmm.. Maybe the task was not
started?
private void
WriteToLog(string text)
{
Task task =
WriteToLogAsync(text);
task.Start();
task.Wait();
}
This
throws InvalidOperationException: Start may not be called on a promise-style
task.
Version
3:
Hmm..
Task.RunSynchronously
sounds
promising.
private void
WriteToLog(string text)
{
Task task =
WriteToLogAsync(text);
task.RunSynchronously();
}
This
throws InvalidOperationException: RunSynchronously may not be called on a
task not bound to a delegate, such as the task returned from an asynchronous
method.
Version
4 (the
solution):
private
void WriteToLog(string text)
{
var task = Task.Run(async () => {
await WriteToLogAsync(text); });
task.Wait();
}
This
works. So, 2 and 3 are the wrong tools. But 1? What's wrong with 1 and what's the
difference to 4? What makes 1 cause a freeze? Is there some problem with the task
object? Is there a non-obvious deadlock?
No comments:
Post a Comment