How to use asynchronous flow in c# 8

Time:2021-7-29

Asynchronous programming has been popular for many years. The async and await keywords introduced by. Net make asynchronous programming more readable. However, it is a pity that asynchronous data flow cannot be processed before c# 8 until c# 8IAsyncEnumerable<T>To solve this problem.

Speaking ofIAsyncEnumerable<T>, I have to say it firstIEnumerable<T>, as we all know, it iterates the collection set in a synchronous way, and hereIAsyncEnumerable<T>It is asynchronous, in other words:IAsyncEnumerable<T>The calling thread is not blocked during the iteration of the collection.

IAsyncDisposable, IAsyncEnumerable<T>, IAsyncEnumerator<T>

Asynchronous iteratorAllow us to process data asynchronously. Before that, we need to understand the following three interfaces:Iasyncdisposable, iasyncenumerable < T > and iasyncenumerator < T >, they are all introduced in. Net standard 2.1. The following code snippet shows the definitions of these three interfaces.


public interface IAsyncDisposable
{
    ValueTask DisposeAsync();
}

public interface IAsyncEnumerable<out T>
{
    IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken
    token = default);
}

public interface IAsyncEnumerator<out T> : IAsyncDisposable
{
    ValueTask<bool> MoveNextAsync();
    T Current { get; }
}

Why use asynchronous iterators

Imagine that you have a data access layer that needs to read all data from the database at one time. To use this function, you can directly call the asynchronous methods provided by the bottom layerXXXAsycImplement asynchronous calls and return all data at once.

As long as not all the data is presented on the page, the problem of this solution is not too big. Most of the time, it is throughPaging readIn fact, another good practice in this regard is to return the data to the caller immediately when the data is available.

To be exact, you can use asynchronous iterators here. If your method is synchronous return, you can usereturn yield+Return valueIEnumerable<T>Unfortunately, this method is not extensible because it needs to block the calling thread.

The best solution isreturn yield+Return valueIAsyncEnumerable<T>Pattern, the asynchronous iterator method returnsIAsyncEnumerable<T>Instance, and can contain one or moreyield returnsentence.

Creating asynchronous iterators in c#8

The following code snippet shows a returnTask<IEnumerable<T>>Type, as shown in the following code:


    class Program
    {
        const int DELAY = 1000;
        const int MIN = 1;
        const int MAX = 10;

        public static async Task Main(string[] args)
        {
            foreach (int number in await GetData())
            {
                Console.WriteLine($"{DateTime.Now}: number={number}");
            }

            Console.ReadLine();
        }

        public static async Task<IEnumerable<int>> GetData()
        {
            List<int> integers = new List<int>();
            for (int i = MIN; i <= MAX; i++)
            {
                await Task.Delay(DELAY);
                integers.Add(i);
            }
            return integers;
        }
    }

How to use asynchronous flow in c# 8

When running the above application, it will wait 10s before putting all 1-10 digital outputs on the console, although thisGetDataIt is asynchronous, but in the end, it is output at one time instead of every second one by one.

At this time, the yield keyword can be involved. It was introduced in c# 2.0 and is often used for executionState iterationAnd return data from the set one by one. You don’t need to create a set (integers) as above and then return it. The following code fragment modifies the GetData method and combines the yield keyword. The code is as follows:


static async IAsyncEnumerable<int> GetData()
{
   for (int i = MIN; i < MAX; i++)
   {
      yield return i;
      await Task.Delay(DELAY);  
   }
}

Using asynchronous iterators in C #8

To useAsynchronous flow, you need to add an await keyword before foreach, as shown in the following code:


        public static async Task Main(string[] args)
        {
            await foreach (int number in GetData())
            {
                Console.WriteLine($"{DateTime.Now}: number={number}");
            }

            Console.ReadLine();
        }

The following is the complete code for reference only.


    class Program
    {
        const int DELAY = 1000;
        const int MIN = 1;
        const int MAX = 10;

        public static async Task Main(string[] args)
        {
            await foreach (int number in GetData())
            {
                Console.WriteLine($"{DateTime.Now}: number={number}");
            }

            Console.ReadLine();
        }

        static async IAsyncEnumerable<int> GetData()
        {
            for (int i = MIN; i < MAX; i++)
            {
                yield return i;
                await Task.Delay(DELAY);
            }
        }
    }

How to use asynchronous flow in c# 8

A very important feature in c# 8 is supportIAsyncEnumerable<T>, it can make your application code cleaner, more efficient and higher performance.

Translation link: https://www.infoworld.com/art…

More high quality dry goods: see my GitHub: csharpranslate

Recommended Today

Java Engineer Interview Questions

The content covers: Java, mybatis, zookeeper, Dubbo, elasticsearch, memcached, redis, mysql, spring, spring boot, springcloud, rabbitmq, Kafka, Linux, etcMybatis interview questions1. What is mybatis?1. Mybatis is a semi ORM (object relational mapping) framework. It encapsulates JDBC internally. During development, you only need to pay attention to the SQL statement itself, and you don’t need to […]