是否有建议的最佳实践/指导来在类库中公开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的同步版本是否安全,因为该任务被配置为不捕获任何同步上下文以避免潜在的死锁
答案 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;
}