2

我目前正在尝试使用 Microsoft.Bcl.Async 和 .NET 4.0 在 VS 2010 中使用 VS 2012 编写一段代码。对于 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 运行代码则完全不同。async 方法按预期工作,但同步包装器方法只是挂起,并且永远不会产生结果。

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

4

1 回答 1

4

作为一般规则,强烈建议不要使用异步方法的同步包装器。当你使用这种Result方法时,你会冒死锁的风险(正如我在我的博客中描述的那样);此外,Result将包装任何异常,这使您的错误处理更加棘手。

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

就 Async CTP 而言,有许多已知存在的错误(以及更多未公开的错误)。而且它们不会被修复。我强烈建议大家升级到 VS2012。

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

于 2013-09-10T13:38:09.980 回答