Say I have an interface IBackgroundTask
:
public interface IBackgroundTask
{
Task<TaskResult> Execute();
}
The application that uses this reads messages from a queue, and then starts consumer logic to execute a background task for the message.
The interfaces dictates that it should be implemented as a Task
, however sometimes the consumer does not actually need to execute any asynchronous work. In such cases the signature we have to implement would better be TaskResult Execute();
.
But we can't change this interface implementation, and it serves as the base to implement both synchronous and asynchronous work.
For the async work, this works well, we can properly use the async
keyword and await
the async calls (examples: calls to API, disk IO):
public async Task<TaskResult> Execute()
{
await PossiblyLongExternalAPICall();
return new TaskResult();
}
But for a consumer that only does synchronous work (examples: a query to the database), I'd have to implement it like so:
public Task<TaskResult> Execute()
{
ExecuteSyncCode();
return Task.FromResult(new TaskResult()); // is this the right thing to do?
}
Is this considered the right approach for situations like this? I have already read up on this topic and it seems like Task.FromResult
for synchronous code isn't really a bad practice, but I'm wondering if there are better alternatives for this scenario.