博主开始学习编程于11年前,年少时还只会使用cincout ,给单片机点点灯。那时候,类似async/awaitfuture/promise 模型的认知还不是很够,因此一直使用着最传统的Thread 模型实现异步。顶多使用ThreadPool 线程池来实现对线程资源的复用。而现在我们有更现代方法,在.net 环境下可以使用现代C# 提供的async/await关键字方便地实现基于任务异步模型的异步调用。

完整代码下载见:Github

一个基本的异步方法

假设我们定义以下这个异步方法模型,在函数上作用async 关键字实现在控制台异步输出字符串。

static async Task FooAsync()
{
    Console.WriteLine("Foo.");
}

突然发现VS2022的提示说由于没有Task.Run或者await还是同步方法。。。

I0-EBmvhJwdYpy4l2IgLgTg_-sdMogVG296z1DMeBm4.png

根据这个提示我们修改上述的方法使之满足异步方法的要求

static async Task FooAsync()
{
    Task.Run(() => Console.WriteLine("Foo."));
}

为了展示各种简单的异步方法,我们写了以下的demo来演示

namespace AsyncBasic
{
    internal class Program
    {

        static async Task BasicFuncAsync()
        {
            await Task.Run(
                () => Console.WriteLine("Hello Basic Func Async.")
            );
        }

        static async Task LoopFuncAsync()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine($"Loop func {i}.");
                await Task.Delay(100);
            }
        }

        static async Task FooAsync()
        {
            Console.WriteLine("Foo.");
        }

        static async Task<int> BasicFuncWithRetAsync()
        {
            Console.WriteLine("Basic func with return value.");
            await Task.Delay(1000);
            return 10086;
        }

        static async IAsyncEnumerable<int> GenerateEnumerableAsync()
        {
            for (int i = 0; i < 10; ++i)
            {
                yield return i;
                await Task.Delay(100);
            }
        }

        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello Async Basic.");
            Task task1 = LoopFuncAsync();
            Task task2 = BasicFuncAsync();
            Task<int> task3 = BasicFuncWithRetAsync();
            Task.WaitAny(task2, task3);
            Console.WriteLine($"Basic Func Async ret value: {task3.Result}");
            Task.WaitAll(task1, task2, task3);

            Console.WriteLine($"Generate Enumerable Async");
            await foreach (int i in GenerateEnumerableAsync())
            {
                Console.WriteLine($"Async Enumerable: {i}");
            }

        }
    }
}

值得一提的是C# 8.0以后可以使用await foreach 来消费异步产生的列表

本文展示了基本的异步方法使用,计划后续再撰文记录异步方法的取消功能等更高级话题。

演示效果如下:

CXPqf5-lSiNgih-NJra8IQgv1hFt5mmz-M1LfYTVpcc.gif

参考链接

https://learn.microsoft.com/zh-cn/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model

https://www.cnblogs.com/cplemom/p/14290789.html