In learning about asynchronous programming, I have been trying to implement an interface that applies to both Asynchronous and Synchronous classes, but I am seeing conflicting practices.
So take for example, if I was trying to implement an ILight
Interface, with methods On() and Off().
public interface ILight
{
void On();
void Off();
}
With a WiredLight
, the methods are synchronous, and is all quick CPU bound work.
public class WiredLight : ILight
{
private bool _powered;
public void On()
{
_powered = true;
}
public void Off()
{
_powered = false;
}
}
But with a WirelessLight
, the methods are Asynchronous, where there is IO bound work. (Here the methods do not follow the interface signature, but are implemented as async, to avoid async void.)
public class WirelessLight : ILight
{
public async Task On()
{
await EnablePowerAsync();
}
public async Task Off()
{
await DisablePowerAsync();
}
}
Reading around (here and here), the way to do this is just force asynchronous signatures in the interface, then all the synchronous calls would be refactored to be asynchronous (Ref: Async all the way). This sounds fine to me, but I haven't really seen anything about how the synchronous methods (from WiredLight
) should be handled. Unlike this question, there are no IO bound operations, so there is nothing to await. I considered wrapping them in an asynchronous call (return Task.Run(() => { _powered = true; });
), but this is contrary to most recommendations. I also considered simply returning an already completed task(Similar to this or this)
public class WiredLight : ILight
{
public Task OnAsync()
{
_powered = true;
return Task.CompletedTask;
}
}
But presenting the method as Async when runs synchronously is lying, and also against reccomendations. In addition, it looks like returning a Task.CompletedTask
may return the same Task to different calls. I can't tell where this would cause problems at the moment, but it seems like something that would cause problems.
Is there an accepted practice for implementing an async interface on a method that returns nothing and really should be synchronous?