Reputation: 2019
I'm doing something for a windows store app, it's an Universal App project and I'm debugging on a Windows 8.1 notebook and a windows 8.1 Surface Pro 3.
I'm trying to create some nested folders in ApplicationData.Current.LocalFolder. From the constructor of the main screen, I call
CacheManager.InitializeOfflineFiles().Wait();
and the code for CacheManager.InitializeOfflineFiles() is
public static async Task InitializeOfflineFiles()
{
try
{
StorageFolder s1 = await ApplicationData.Current.LocalFolder.CreateFolderAsync("one", CreationCollisionOption.OpenIfExists);
Debug.WriteLine("Created folder one");
StorageFolder s2 = await s1.CreateFolderAsync("two", CreationCollisionOption.OpenIfExists);
Debug.WriteLine("Created folder two");
StorageFolder s3 = await s2.CreateFolderAsync("three", CreationCollisionOption.OpenIfExists);
Debug.WriteLine("Created folder three");
StorageFolder s4 = await s3.CreateFolderAsync("four", CreationCollisionOption.OpenIfExists);
Debug.WriteLine("Created folder four");
}
catch (Exception e)
{
Debug.WriteLine("Windows doesn't love you. Exception: " + e.Message);
}
}
When I debug this, it doesn't get past creating folder "two". No exception logged, no nothing. Also, when I run this without debugging (Ctrl + F5), same result, only dir "one/two" gets created in the local storage.
Is this a case of misunderstanding async programming?
Upvotes: 0
Views: 851
Reputation: 2201
To avoid deadlock, try this:
StorageFolder s1 = await ApplicationData.Current.LocalFolder.CreateFolderAsync("one", CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);
Upvotes: 0
Reputation: 2019
It turns out that i can call the async method from the constructor. In the constructor:
var task = Task.Run(async () =>
{
return await CacheManagerInitializeOfflineFiles();
});
string dummy = task.Result;
The method in same class calling the async method that creates storage dirs:
private async Task<string> CacheManagerInitializeOfflineFiles()
{
await CacheManager.InitializeOfflineFiles();
return "done";
}
I really don't want to put a button "initialize application", that would be bad design :)
Upvotes: 1
Reputation: 149588
This:
CacheManager.InitializeOfflineFiles().Wait();
Is causing your app to deadlock. This is why you're seeing the "hanging" behavior. It is peculiar that you seem to be seeing folder 1 & 2 being created, as i assume this should deadlock when the first await
is executed.
This is the reason you shouldn't block on async code.
Since constructors can't be async, use the "Initialize Pattern" (or other known async initalization patterns) instead to execute your async code:
public Task InitializeAsync()
{
return InitializeOfflineFilesAsync()
}
And from your code, call this from an async
context method, perhaps an event handler:
public async void SomeButtonClickEventHandler()
{
await InitializeAsync();
}
The moral of the story is, don't call asynchronous methods via your constructor.
Upvotes: 1