I have a Portable Class Library (PCL) targeted at Profile158 (Windows Store, .NET 4.5, Silverlight 5, Windows Phone 8). I can easily work with methods that return a type of Task, and it all works as I would expect. Whenever I access the Result property, it finishes running the asynchronous code and returns the result.
However, if I use the async/await keywords in a method inside the PCL, I get a task back. However, when I attempt to access the Result property, it blocks and never returns.
Looking at the debug output window in Visual Studio in both cases I see the same text:
Thread started:
Thread started:
Loaded assembly: Mono.Security.dll [External]
Thread started:
Thread started:
So it appears as if the code is being run, but it never returns to the UI thread. Has anyone else tried to use a PCL with Microsoft.bcl.async in the PCL?
My Mono Droid project is targeted at Android 2.1.
Thanks,
— John
Update:
Here is some additional information about the different scenarios. First, here is code that does work on Mono Droid when written in the UI code:
var task = request.GetResponseAsync();
string html = task.Result.GetResponseText();
I then created the following method in the PCL:
public async Task<string> Test()
{
IHttpResponse responce = await GetResponseAsync();
return responce.GetResponseText();
}
And call it with this code from the Mono UI code:
string html = request.Test().Result;
it never returns…
This is a classic deadlock scenario, as I describe on my blog.
By default,
awaitwill capture a “context” and use it to resume theasyncmethod. This “context” is the currentSynchronizationContextunless it isnull, in which case it’s the currentTaskScheduler.So, you’re calling an
asyncmethod from a UI thread (which provides aSynchronizationContext), then blocking the UI thread by callingResult. Theasyncmethod cannot finish because it is trying to finish on the UI thread, which is blocked.To fix this, follow these guidelines:
asyncall the way down. Don’t callResultorWaitonTasks returned fromasyncmethods; useawaitinstead.ConfigureAwait(false)whenever possible in your library code.You may also find my
async/awaitintro helpful.