I'm currently trying to make a piece of code written in VS 2012, using Microsoft.Bcl.Async and .NET 4.0, work in VS 2010. For VS 2010 I've installed the Async CTP (ver. 3), such that I am able to compile my project written in V S2012.
After quite a lot of trouble getting the Async CTP pack to work, I am now able to compile my project under both VS 2012 as well as VS 2010.
However, I'm seeing some differences in how the code works in run-time. The code I am exercising is shown below:
public class Fetcher
{
public string RunTask()
{
Task<string> task = TaskEx.Run(() => RunTaskAsync());
return task.Result;
}
public async Task<string> RunTaskAsync()
{
await TaskEx.Delay(1);
return "Hello";
}
}
Basically, what I have is an async method, for which I need to have a sync wrapper around, such that clients can call either the async or sync version of the method.
The problem: When running the code from VS 2012 both method will return the result "Hello", and more importantly, both methods will exit properly. Running the code from VS 2010, however, is a far different story. The async method works as intended, but the sync wrapper method simply hangs, and the result is never produced.
Since I am fairly new to the concept of TPL and async/wait, I'm having some trouble explaining the behavior I am seeing here. Is there some sort of limitations in the Async CTP that kicks in, that I am not aware of, or am I doing this in a conceptually wrong way?
As a general rule, synchronous wrappers around asynchronous methods are strongly discouraged. When you use the Result
approach, you run the risk of deadlock (as I describe on my blog); also, Result
will wrap any exceptions, which makes your error handling much trickier.
So I'd say "don't do that."
As far as the Async CTP goes, there are a number of bugs that are known to exist (plus several more that are not public). And they're not going to be fixed. I strongly recommend upgrading everyone to VS2012.
For this particular issue, it may be performance-related. E.g., Task.Delay(1)
returns a task that will complete almost immediately, so there's a race condition between starting the delay and the await
which checks whether the task is already complete. So it's possible that performance improvements in the official Microsoft.Bcl.Async
are causing the difference in behavior.