将async方法作为同步调用时Async CTP和Bcl.Async之间的差异

时间:2013-09-10 13:34:24

标签: task-parallel-library async-await async-ctp

我目前正在尝试使用Microsoft.Bcl.Async和.NET 4.0在VS 2012中编写一段代码,在VS 2010中工作。对于VS 2010,我安装了Async CTP(版本3) ,这样我就可以编译用V S2012编写的项目。

使Async CTP包运行起来非常麻烦,我现在能够在VS 2012和VS 2010下编译我的项目。

但是,我发现代码在运行时的工作方式存在一些差异。我正在行使的代码如下所示:

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";
    }        
}

基本上,我所拥有的是异步方法,我需要有一个同步包装器,这样客户端就可以调用该方法的异步或同步版本。

问题:从VS 2012运行代码时,两种方法都会返回结果“Hello”,更重要的是,两种方法都会正常退出。然而,从VS 2010运行代码是一个完全不同的故事。异步方法按预期工作,但同步包装器方法只是挂起,结果永远不会产生。

由于我对TPL和异步/等待的概念相当新,我在解释我在这里看到的行为时遇到了一些麻烦。 Async CTP中是否存在某些限制,我不知道,或者我是否以概念错误的方式执行此操作?

1 个答案:

答案 0 :(得分:4)

作为一般规则,synchronous wrappers around asynchronous methods are strongly discouraged。当您使用Result方法时,run the risk of deadlock(正如我在博客中描述的那样);此外,Result将包装任何异常,这使您的错误处理更加棘手。

所以我会说“不要那样做。”

就Async CTP而言,已知存在许多错误(还有一些不公开的错误)。他们不会被修复。我强烈建议将所有人升级到VS2012。

对于这个特定问题,它可能与性能有关。例如,Task.Delay(1)返回一个几乎立即完成的任务,因此在启动延迟和await之间存在竞争条件,检查任务是否已经完成。因此,官方Microsoft.Bcl.Async中的性能改进可能会导致行为上的差异。