Introduction
In C#, you can use the async and await keywords to create asynchronous methods. However, not all methods can be easily turned into asynchronous methods using async Task. Whether or not you can make a method asynchronous depends on whether that method has asynchronous operations to perform.
Key Points To Consider When Making Methods Async
Method Must Have Asynchronous Operations: To make a method asynchronous, it should have one or more asynchronous operations to perform, such as I/O-bound operations like file or network access, CPU-bound operations that benefit from parallelism, or awaiting other asynchronous methods. Simply adding async to a method without actual asynchronous operations won’t make it asynchronous.
public async Task MyAsyncMethod()
{
// Asynchronous operations using await
await DoSomethingAsync();
}
Use async Task for Asynchronous Methods: When you have asynchronous operations within a method, you can make it asynchronous by marking it with the async keyword and changing its return type to Task or a more specialised type like Task<T>. The async keyword signals to the compiler that the method contains await expressions and asynchronous behaviour.
Async Naming Convention: It’s a good practice to name asynchronous methods with an “Async” suffix to indicate their asynchronous nature. For example, MyMethod can become MyMethodAsync.
Avoid Mixing Synchronous and Asynchronous Code: Be cautious when mixing synchronous and asynchronous code within a method. Mixing can lead to deadlocks and degrade the benefits of asynchrony. I always prefer using asynchronous counterparts of synchronous methods whenever available.
// Avoid mixing synchronous and asynchronous code like this
public async Task MyAsyncMethod()
{
// Synchronous operation
var result = SomeSynchronousMethod();
// Asynchronous operation
await DoSomethingAsync();
}
Consider Using async ValueTask for Performance: In some cases, you may consider using async ValueTask instead of async Task, especially for high-performance scenarios where the overhead of creating a Task object is a concern. ValueTask can be more efficient when the result can be provided synchronously.
public async ValueTask MyAsyncMethod()
{
// Asynchronous operations using await
await DoSomethingAsync();
}
Conclusion
You can use async Task (or ValueTask) to make a method asynchronous, but the it must contain asynchronous operations that benefit from asynchrony. Simply marking a it as async without such operations won’t result in any asynchronous behaviour.
Always use asynchronous methods when dealing with I/O-bound or CPU-bound operations that can be parallelised or require non-blocking behaviour.
The official documentation for async can be found here: – https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-scenarios.
I have written a number of other posts on asynchronous programming here: – Choose await/async over Task Alone, Understanding Task.Yield, Asynchronous Task.Delay.