kas*_*rhj 15 .net c# async-await
我有一个简单的界面
public interface SomethingProvider
{
public Something GetSomething();
}
Run Code Online (Sandbox Code Playgroud)
为了"使"它异步,我会这样做
public interface SomethingProvider
{
public Task<Something> GetSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)
虽然接口现在暗示GetSomething
是异步的,但它允许同步执行,如果同步结果足够快,这很好.如果它阻塞,那么我可以将责任归咎于实现程序员对接口的不良实现.
因此,如果后一个接口是通过足够快的阻塞实现来实现的,那么后一个接口比前者更灵活,因此是优选的.
在这种情况下,如果对方法的调用花费的时间超过一些时间,我是否应该重写所有接口以返回任务?
编辑:
我想强调的是,这不是关于任务是什么或它们如何工作的问题,而是与定义它们时接口的固有未知实现有关的设计问题.在编写接口时,允许同步和异步实现似乎是有益的.
第三个"解决方案"可能是前两个的一些合并:
public interface SomethingProvider
{
public Something GetSomething();
public Task<Something> GetSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)
但这打破了利斯科夫的替代原则,只给实施者带来了混乱.
Ste*_*ary 10
这个设计问题与此并行IDisposable
.在编写接口时,您必须知道派生类型是否"可能"需要IDisposable
,并且如果它们将会从中派生出来.像测试存根这样的非一次性类型只是实现了一个noop Dispose
.
类似地,当您编写接口时,您必须知道派生类型是否"可能"将使用异步实现.
请注意,派生类型的问题是:"实现是否会自然异步?",而不是 "实现是否会很快?".速度与它无关.您应该考虑的唯一事情是实现是否可以是自然异步的(即,使用I/O或其他异步方法).
当您编写接口时,通常会考虑一个(或少数)实现; 我建议你在决定使接口方法异步时只考虑那些.你可以走极端,只是让每个接口方法都异步,但这就像IDisposable
在任何地方使用- 不是我推荐的模式.
所以,我想说如果你的(当前)实现对于特定方法都是同步的,那么使该方法同步; 否则,使它异步.
如您所述,异步方法签名在技术上意味着实现可能是异步的.测试存根等可用于Task.FromResult
同步实现异步签名.就个人而言,我认为这对于存根实现是完全可以接受的; 但是,当所有当前的实现都是同步的时候,我不建议将方法设为async"以防万一".
另外,我强烈反对签名.这将要求实现者包装同步异步或同步异步,这两者都不是理想的.
归档时间: |
|
查看次数: |
699 次 |
最近记录: |