在库代码中提供API的同步和异步版本

时间:2013-06-07 05:19:16

标签: c# .net task-parallel-library

是否有建议的最佳实践/指导来在类库中公开API的同步和异步版本?例如,如果我在类库中定义了以下两种方法:

  public Task<string> GetSomeDataAsync()
    {
        //typically an IO operation that would be awaited on, simplified to return a Task for illustration
        return Task<string>.Factory.StartNew( () =>  "foo");
    }

    public string GetSomeDataSync()
    {
        var task = GetSomeDataAsync();
        task.ConfigureAwait(continueOnCapturedContext: false);
        return task.Result;
    }

以上内容可以托管在Winform / WPF / Console / ASP.NET客户端应用程序中。 客户端使用上面使用task.Result的同步版本是否安全,因为该任务被配置为不捕获任何同步上下文以避免潜在的死锁

2 个答案:

答案 0 :(得分:3)

我认为最好的建议来自Stephen Toub的两篇文章:

第二个对你更有意义。简而言之,它说你不应该这样做。如果你的方法的调用者决定同步等待,他仍然可以做出这个选择,并且他处于比你更好的位置(因为他知道环境,所以他应该知道死锁是否是一个问题,例如)。

  

以上内容可以托管在Winform / WPF / Console / ASP.NET客户端应用程序中。客户端使用上面使用task.Result的同步版本是否安全,因为该任务被配置为不捕获任何同步上下文以避免潜在的死锁

你错了。 ConfigureAwait()不会以任何方式修改Task(特别是因为此时Task已在执行)。它所做的只是返回ConfiguredTaskAwaitable,如果你await,它将不会在捕获的上下文中恢复。

这意味着您的方法仍然会死锁。

答案 1 :(得分:-1)

MS支持异步模式有3个“主要”选项。我建议你选择其中一种模式并坚持下去......看起来你已经走向了“基于任务的异步模式”,所以你需要很少的mod才能符合模式。这允许您以对其他消费者统一和直观的方式创建方法......他们将了解MS构建的.NET库中的模式。有关详细信息,请参阅此处:

概述:http://msdn.microsoft.com/en-us/library/jj152938.aspx

任务异步模式:http://msdn.microsoft.com/en-us/library/hh873175.aspx

使用支持取消令牌的任务异步模式的方法示例:

public Task<string> GetSomeDataAsync(CancellationToken cancellationToken = null)
{
    return Task<string>.Factory.StartNew(() =>  "foo", cancellationToken);
}

// NOTE: no need to append Sync to the method name, redundant.
public string GetSomeData()
{
    var task = GetSomeDataAsync();
    task.ConfigureAwait(continueOnCapturedContext: false);
    return task.Result;
}