Important Facts of Asynchronous Programming in .NET

Modern apps make extensive use of file and networking I/O. I/O APIs traditionally block by default, resulting in poor user experiences and hardware utilization unless you want to learn and use challenging patterns.

Task-based async APIs and the language-level asynchronous programming model invert this model, making async execution the default with few new concepts to learn.

Async code has the following characteristics:

  • Handles more server requests by yielding threads to handle more requests while waiting for I/O requests to return.
  • Enables UIs to be more responsive by yielding threads to UI interaction while waiting for I/O requests and by transitioning long-running work to other CPU cores.
  • Many of the newer .NET APIs are asynchronous.
  • It’s easy to write async code in .NET

One of the main advantages of using asynchronous methods is with I/O-based code.

By doing an await, you can let a thread be reused to do other work while the I/O is in flight.

The biggest misunderstanding about Asynchronous programming in many developers is asynchronous method automatically spawns a new thread, and that is not the case.

Recent improvements Microsoft has made towards Asynchronous programming is “Generalized Async Return Types

This means that you’re no longer limited to using Task or Task<T> as the return type for an asynchronous method. As long as the return type satisfies the asynchronous pattern, you’re good. Using this new ValueTask, you can avoid memory allocations, which can help in addressing performance issues.

Top Nuget Packages that Microsoft recommend for asynchronous programming are “System.Collections.Concurrent” and “System.Collections.Immutable“.

System.Collections.Immutable provides collections that allow a developer to use a collection (e.g. ConcurrentBag or ConcurrentDictionary) in a concurrent fashion safely. Therefore, the developer doesn’t need to do their own locking mechanisms to use the collection. Immutable collections allow developers to share collections safely because updates are only seen by the code that made the update.

Avoid void as a return type for asynchronous methods at all costs.

The only time it’s valid to do this is with an event handler. Otherwise, asynchronous methods should always return a Task type.

Immutable structures are very important when working with concurrent programming.

The main advantage with immutable data types is that you can share them across multiple tasks without worrying about synchronizing their contents. By their definition, they’re immutable, so if a task decides to “change” an immutable object, it will get a new version of that object. If another task has a reference to the original immutable object, it doesn’t change.

Take advantage of C# features to write immutable structures.

This means defining fields with the readonly keyword and properties that only have getters (not even private setters). Also, C# now allows you to specify a method parameter with the in keyword, which means that reference cannot be changed.

That’s all for now. I hope these facts will help you while doing Asynchronous Programming for your projects 🙂