Reputation: 849
I am trying to write a function to load some data from the roaming folder on a windows 8 store app.
I get a deadlock (hang) on roamingLoad.Wait() in the Load method;
What is the correct way to do this? What is being done wrong below?
Edit: I should point out that if I step though it in the debugger it works perfectly.
And is there a way to do it without the top method becomeing async? If I do that then every calling method must say await to block until it's done no?
public override bool Load(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
{
if (PreferRoaming && SupportsRoamingSave)
{
try
{
Task<bool> roamingLoad = RoamingLoadAsync(in_FileNameAndDirectory, in_StreamTask);
roamingLoad.Wait();
return roamingLoad.Result;
}
catch (Exception error)
{
return false;
}
}
return Load(in_FileNameAndDirectory, in_StreamTask);
}
private async Task<bool> RoamingLoadAsync(string inFileNameAndDirectory, StreamTask inStreamTask)
{
try
{
StorageFolder roamingFolder = ApplicationData.Current.RoamingFolder;
StorageFile sampleFile = await roamingFolder.GetFileAsync(inFileNameAndDirectory);
using (Stream stream = await sampleFile.OpenStreamForReadAsync())
inStreamTask(stream);
}
catch (Exception error)
{
return false;
}
return true;
}
Upvotes: 1
Views: 130
Reputation: 456987
What is the correct way to do this?
You're running into a common deadlock problem (that I explain in full on my blog). To summarize, you should not use Task.Wait
or Task<T>.Result
on an asynchronous task. Instead, you should use await
.
In order to use await
, your method must be async
. This means that this signature is just fundamentally incompatible with asynchronous operations:
public override bool Load(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
Assuming that the bool
result is in fact important (which is certainly debatable - returning bool
results instead of exceptions is kind of '80s, wouldn't you say?), the correct way to write this is to change the base class signature so that it supports asynchronous operations:
public override async Task<bool> LoadAsync(string in_FileNameAndDirectory, StreamTask in_StreamTask, bool in_PreferRoaming)
{
if (PreferRoaming && SupportsRoamingSave)
{
try
{
return await RoamingLoadAsync(in_FileNameAndDirectory, in_StreamTask);
}
catch (Exception error)
{
return false;
}
}
return Load(in_FileNameAndDirectory, in_StreamTask);
}
Upvotes: 1