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, await
will capture a "context" and use it to resume the async
method. This "context" is the current SynchronizationContext
unless it is null
, in which case it's the current TaskScheduler
.
So, you're calling an async
method from a UI thread (which provides a SynchronizationContext
), then blocking the UI thread by calling Result
. The async
method cannot finish because it is trying to finish on the UI thread, which is blocked.
To fix this, follow these guidelines:
async
all the way down. Don't call Result
or Wait
on Task
s returned from async
methods; use await
instead.ConfigureAwait(false)
whenever possible in your library code.You may also find my async
/await
intro helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With