Working with Async Streams in C#

C# Programming Guide

Asynchronous programming approaches allow developers to increase the responsiveness of their applications. One of the numerous new language features introduced in C# 8 was async streams. Async streams are an excellent approach to representing asynchronous data sources that the data consumer may manage.

Async streams were introduced in C# 8 to provide a way to work with asynchronous data streams. They are similar to regular streams, but have some additional features that make them well suited for working with asynchronous data.

In this programming tutorial, we will discuss async streams and how they can be used in C# software development environments.

Read: Best Microsoft Certifications for Developers

What are Asynchronous Streams in C#?

Async Streams were introduced in C# 8.0 and allow programmers to asynchronously iterate over a sequence of values. Async streams are more efficient than traditional synchronous streams since they do not block the currently executing thread.

Asynchronous streams can read data from a data source asynchronously, process this data, and write the result back to a destination. They can read or write data from – and to – a data source asynchronously. They allow developers to write to several destinations simultaneously, which improves the performance of your applications by using multiple cores or machines.

Coders can use asynchronous streams to process this data asynchronously, thus enhancing performance with optimal resource usage. Async streams are particularly useful when working with large collections of data, or when working with data that is being constantly updated (such as a live feed). Async streams ensure that your application remains responsive while it is processing these large volumes of data.

With the introduction of.NET Standard 2.1, the interfaces IAsyncDisposable, IAsyncEnumerableT>, and IAsyncEnumeratorT> were introduced. Programmers can use these APIs to operate with asynchronous streams.

Here is some example code showing how the IAsyncDisposable, IAsyncEnumerableT>, and IAsyncEnumeratorT>interfaces are defined in C#:

public interface IAsyncDisposable
{
    ValueTask DisposeAsync();
}
public interface IAsyncEnumerable
{
    IAsyncEnumerator GetAsyncEnumerator(CancellationToken
    token = default);
}
public interface IAsyncEnumerator : IAsyncDisposable
{
    ValueTask MoveNextAsync();
    T Current { get; }
}

Read: Top Ten Security Testing Tools for Developers

What are the Benefits of Asynchronous Streams in C#?

To better understand the benefits of C# Asynchronous streams and why developers would use them, let us consider a scenario where you are building an online shopping cart application that reads items from a store and displays them in your cart. Suppose the item store is an online database of over a million items, and you want to read them from this database.

Typically, you may take advantage of an asynchronous method to read the items from the item store and return pages of data to the user interface. However, you might have to read a lot of data as the user scrolls from one page to another. The optimal solution, in this case, allows you to send the data back to the caller as soon as it is available.

This is precisely when asynchronous streams come in handy. A method that uses an Asynchronous stream returns an instance of IAsyncEnumerable and includes one or more yield return statements. Although programmers can use the yield return statement with IEnumerable in a synchronous method, this approach would block calls and, therefore, would not scale.

It would help if you used yield return statements for optimal performance in asynchronous methods returning IAsyncEnumerable instead. To implement Asynchronous streams in a method, you should make the method asynchronous using the async keyword and return an instance of IAsyncEnumerable. Additionally, your async method should include one or more yield return statements. Async streams integrate well with LINQ, allowing you to use all of the LINQ methods on asynchronous data sources.

What are the Drawbacks of Asynchronous Streams?

There are some potential drawbacks to using async streams in C#, however, including:

  • Because async streams use lazy evaluation, your code may not begin executing until you start enumerating the results of the stream.
  • If an error occurs during the execution of an async stream, it may be difficult to debug since the exception will likely be thrown at a later time.
  • Async streams require more memory than equivalent synchronous code since they keep track of intermediate results.

How to Program Asynchronous Streams in C#

The await keyword must be used before the foreach keyword when trying to enumerate the items of an asynchronous stream. It is important to note that when you add the await keyword to a method used to enumerate the Asynchronous stream, the method must be defined with the async modifier and it must return an appropriate type.

The following code example illustrates how you can use the yield statement in an async method to work with Asynchronous streams in C#:

 static async Task Main(string[] args)
        {
            await foreach (int n in Producer())
            {
                Console.WriteLine(n);
            }
            Console.Read();
        }
        public static async IAsyncEnumerable Producer()
        {
            for (int i = 0; i < 10; i++)
            {
                await Task.Delay(10);
                yield return i;
            }
        }

You can read how to handle exceptions in Asynchronous methods like async() and await() in our programming tutorial: Handling Exceptions in Asynchronous Methods in C#.

What are Some Use Cases for Asynchronous Streams?

Asynchronous streams are used in real-life scenarios to process large amounts of data, perform IO operations, and make a program more responsive. For example, if you have to process 1 million records from a database, you could use Asynchronous streams, which will make your program faster.

You can also use Asynchronous streams for performing IO operations which will be very useful for an application where users need to wait for that operation, like uploading or downloading files from the internet.

Final Thoughts on Asynchronous Stream in C#

Async streams are a new feature in C# 8.0 that allows developers to easily consume and produce async sequences of data. By using async streams, you can avoid blocking UI threads and make better use of CPU resources. You can boost your application’s performance considerably by consuming and creating data streams asynchronously.

Read: C#: How to Perform Async File Operations

Joydip Kanjilal
Joydip Kanjilal
A Microsoft Most Valuable Professional in ASP.NET, Speaker, and Author of several books and articles. More than 25 years of experience in IT with more than 18 years in Microsoft .NET and its related technologies. He was selected as a Community Credit Winner at http://www.community-credit.com several times. He has authored 8 books and more than 500 articles in some of the most reputed sites worldwide including MSDN, Info World, CodeMag, Tech Beacon, Tech Target, Developer, CodeGuru, and more.

More by Author

Must Read