【发布时间】:2018-11-04 10:10:05
【问题描述】:
在学习异步编程时,我一直在尝试实现一个既适用于异步类又适用于同步类的接口,但我看到了相互冲突的做法。
举个例子,如果我尝试使用 On() 和 Off() 方法实现 ILight 接口。
public interface ILight
{
void On();
void Off();
}
使用WiredLight,这些方法是同步的,并且都是快速的 CPU 密集型工作。
public class WiredLight : ILight
{
private bool _powered;
public void On()
{
_powered = true;
}
public void Off()
{
_powered = false;
}
}
但是对于WirelessLight,这些方法是异步的,其中有 IO 绑定工作。 (这里的方法不遵循接口签名,而是以异步方式实现,以避免异步无效。)
public class WirelessLight : ILight
{
public async Task On()
{
await EnablePowerAsync();
}
public async Task Off()
{
await DisablePowerAsync();
}
}
阅读(here 和here),这样做的方法只是在接口中强制异步签名,然后所有同步调用将被重构为异步(参考:Async all the way)。这对我来说听起来不错,但我还没有真正看到有关如何处理同步方法(来自WiredLight)的任何信息。与this 问题不同,没有IO 绑定操作,因此没有什么可以等待的。我考虑将它们包装在异步调用中(return Task.Run(() => { _powered = true; });),但这与大多数recommendations 相反。我也考虑过简单地返回一个已经完成的任务(类似于this 或this)
public class WiredLight : ILight
{
public Task OnAsync()
{
_powered = true;
return Task.CompletedTask;
}
}
但是在同步运行时将方法呈现为异步是谎言,并且也反对推荐。此外,看起来返回 Task.CompletedTask 可能会将相同的任务返回给不同的调用。目前我不知道这会在哪里引起问题,但似乎会引起问题。
对于不返回任何内容并且确实应该同步的方法实现异步接口,是否存在公认的做法?
【问题讨论】:
-
是什么让你想把这个接口写成异步的?
-
“我也考虑过简单地返回一个已经完成的任务”——是的,这是正确的做法。我一直使用
Task.FromResult()而不是CompletedTask,如果您担心任务对象身份,那么FromResult()可能会解决这个问题。 -
@zaitsman 使用上面的示例,我已经有一个实现
ILight的WiredLight,我刚刚添加了WirelessLight,它还需要实现ILight。 (基本上我在 Async Zombie 病毒中)
标签: c# .net asynchronous interface async-await