SuperJMN
SuperJMN

Reputation: 13972

Async method won't return when called

I'm having a bad time with this. I'm trying to make a async method that returns the contents of a local file as string. This is my approach:

private static async Task<string> ReadContentsAsString(string fileName)
{
    var uri = new Uri(string.Format(@"ms-appx:///{0}", fileName));
    var file = await StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().ConfigureAwait(false);
    var stream = await file.OpenStreamForReadAsync().ConfigureAwait(false);

    using (var streamReader = new StreamReader(stream))
    {                
        return await streamReader.ReadToEndAsync();
    }
 }

Unfortunately, after the execution reaches the end of my method, the application waits forever. It hangs completely. It's being called at the very beginning, when the splash screen still shows (Windows Phone 8.1)

What do I miss?

Upvotes: 3

Views: 1207

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456457

I suspect that further up your call stack, your code has a call to Task.Wait or Task<T>.Result. This can cause a deadlock that I describe on my blog.

In summary, what happens is that when await is used on a task, by default it will capture the current "context" and use that context to resume the async method. In this case, the context is the UI context, which is associated with the single UI thread. If code further up the call stack is calling Wait or Result, then it's blocking the UI thread, which prevents the async method from finishing.

Upvotes: 4

Romasz
Romasz

Reputation: 29792

Your method is working as it should. I suspect that you are encountering this issue while debugging.

I also have noticed (sometimes) such a behaviour when debugging asyc method (here is a link to the question) - the program never returns from the method and just hangs - I don't know the exact reason of this. To test it just try to run your method like this - for example upon button click:

private async void firstBtn_Click(object sender, RoutedEventArgs e)
{
    Debug.WriteLine("Before method");
    string readValue = await ReadContentsAsString("TextFile1.txt");
    Debug.WriteLine(string.Format("Read value: {0}", readValue));
}

As I've tested on device - it should work, but if I set a breakpoint inside your method - it will hang.

Upvotes: 2

Related Questions