The Task class is a vital element to async/await operations. Async functions must return Task-wrapped objects, as such:
public async Task<int> LongCalculation()
{
int value = await SomeLongAsyncTask();
return value;
}
Work with async/await long enough and you'll come across Task.CompletedTask. According to the official documentation. This static property that simply "returns a task whose Status property is set to RanToCompletion.".
And? Why would I use it?
Glad you asked. I've found two uses:
To avoid warnings in non-async async functions
Sometimes you define a function that may later be async, but the first implementation isn't (hence the "non-async async"). When you go to compile, the compiler complains that your async function doesn't have an await in it.
Here's a simple way around that:
public async Task<int> LongCalculation()
{
await Task.CompletedTask;
int value = 123;
return value;
}
During implementations of interfaces implemented as sync
You may want to define an interface that later can be used either Sync or Async. Such as:
public interface IDoSomeWork
{
Task Work();
}
Given this, you can create two different implementations, one sync, the other async. Here's the sync version:
Implementation #1: Syncpublic class TestOneSync : IDoSomeWork
{
public Task Work()
{
// Do some sync work
return Task.CompletedTask;
}
}
Notice this version does NOT include the async in the function definition. All that's needed is to return a Task object. In this case Task.CompletedTask works great.
public interface TestTwoAsync : IDoSomeWork
{
public async Task Work()
{
// Do some async work
return;
}
}
In this case the Work function truly is async, all only needs a simple return.
Most likely there are other uses for Task.CompletedTask, but here are two simple examples.