【发布时间】:2015-01-01 07:31:11
【问题描述】:
我有一个界面
interface IFoo
{
Task<Bar> CreateBarAsync();
}
创建Bar有两种方法,一种是异步的,一种是同步的。我想为这两种方法分别提供一个接口实现。
对于异步方法,实现可能如下所示:
class Foo1 : IFoo
{
async Task<Bar> CreateBarAsync()
{
return await AsynchronousBarCreatorAsync();
}
}
但是我应该如何实现使用同步方法创建Bar的类Foo2?
我可以实现同步运行的方法:
async Task<Bar> CreateBarAsync()
{
return SynchronousBarCreator();
}
然后编译器将警告不要在方法签名中使用async:
此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。
或者,我可以实现显式返回Task<Bar>的方法。在我看来,代码会看起来不那么可读:
Task<Bar> CreateBarAsync()
{
return Task.Run(() => SynchronousBarCreator());
}
从性能的角度来看,我想这两种方法的开销大致相同,或者?
我应该选择哪种方法;同步实现async 方法或将同步方法调用显式包装在Task 中?
编辑
我正在处理的项目实际上是一个 .NET 4 项目,带有来自 Microsoft Async NuGet 包的 async / await 扩展。在 .NET 4 上,Task.Run 然后可以替换为 TaskEx.Run。在上面的示例中,我有意识地使用了 .NET 4.5 方法,希望使主要问题更加清晰。
【问题讨论】:
-
对于这种情况,我相信
Task.FromResult(SynchronousBarCreator())比Task.Run(...)更好,因为它实际上并没有调度和运行任务来获得结果。 -
SynchronousBarCreator是否长时间运行?是 CPU 受限,还是花时间等待其他事情? -
就我现在正在处理的情况而言,它不会长期运行。但它可能会出现在即将到来的场景中。
-
这很令人困惑,也不是最佳实践。我的建议是:创建一个同时具有同步和异步方法的接口这种方法的一个很好的例子是 WebClient、EF 等。 . 或创建 2 个接口一个用于同步,另一个用于异步方法。
标签: c# .net asynchronous task-parallel-library async-await