I’m just experimenting with WinRT and one demo app i’m creating is a basic “notepad” style app which loads/saves to local storage. Whilst I’m familiar with the proper async approach for building WinRT apps, my demo app is using a synchronous Load to keep things simple.
The problem is that when a call is made to Load, it works 2 out of 3 times and the rest of the time the app hangs on the call var result = await FileIO.ReadTextAsync(storageFile);
public class ContentStorage : IContentStorage
{
private const string FileName = "contents.txt";
public string Load()
{
return LoadAsync().Result;
}
public void Save(string content)
{
SaveAsync(content);
}
private static async Task<string> LoadAsync()
{
var storageFile = await LocalFolder.GetFileAsync(FileName);
var result = await FileIO.ReadTextAsync(storageFile);
return result;
}
private static async void SaveAsync(string content)
{
var storageFile = await LocalFolder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
FileIO.WriteTextAsync(storageFile, content);
}
private static StorageFolder LocalFolder
{
get { return ApplicationData.Current.LocalFolder; }
}
}
Am I doing something extraordinarily stupid here?
FWIW, I experimented with changing Load to just explicitly block on each step and this improves the hanging to 1 in 20, but I still don’t understand why it’s hanging at all…
public string Load()
{
var storageFile = LocalFolder.GetFileAsync(FileName).AsTask().Result;
var result = FileIO.ReadTextAsync(storageFile).AsTask().Result;
return result;
}
Not really. Mixing synchronous with asynchronous code is extremely complex. It’s far simpler to just use
asynceverywhere.When an
asyncmethod continues execution after waiting for a task, it will return to its original context by default. (I cover this in more detail in myasync/awaitblog post). Some contexts (such as UI contexts) only permit a single thread; if that thread is blocked (e.g., onTask.Result), then theasyncmethod cannot enter that context to complete its execution. This causes a deadlock.For more information:
async/awaitFAQ has a lot of detail on the context capture and resume.This deadlock is famous enough that it’s actually been demo’d by Microsoft: