Skip to content

async await.cs

文件信息

  • 📄 原文件:01_async_await.cs
  • 🔤 语言:csharp

完整代码

csharp
// ============================================================
//                      异步编程(async/await)
// ============================================================
// C# 的 async/await 是基于 Task 的异步模型(TAP)
// async 方法在遇到 await 时会释放线程,不阻塞调用线程
// 【核心原则】IO 密集型用 async/await,CPU 密集型用 Task.Run

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class AsyncAwaitDemo
{
    // ----------------------------------------------------------
    // 1. 基本 async/await
    // ----------------------------------------------------------
    // async 方法返回 Task(无返回值)或 Task<T>(有返回值)
    // 在最顶层(Main)用 await 等待任务完成

    static async Task<string> FetchDataAsync(string url)
    {
        // 模拟网络请求延迟
        await Task.Delay(100);  // 非阻塞等待
        return $"来自 {url} 的数据";
    }

    static async Task<int> ComputeAsync(int n)
    {
        await Task.Delay(50);  // 模拟计算延迟
        return n * n;
    }

    // ----------------------------------------------------------
    // 2. 异常处理
    // ----------------------------------------------------------
    static async Task<string> FetchWithErrorAsync(bool shouldFail)
    {
        await Task.Delay(50);
        if (shouldFail)
            throw new InvalidOperationException("模拟的网络错误");
        return "成功获取数据";
    }

    // ----------------------------------------------------------
    // 3. 取消令牌(CancellationToken)
    // ----------------------------------------------------------
    // 【最佳实践】长时间运行的异步操作应支持取消

    static async Task<string> LongRunningTaskAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("长任务开始...");
        for (int i = 0; i < 10; i++)
        {
            cancellationToken.ThrowIfCancellationRequested();
            await Task.Delay(100, cancellationToken);
            Console.Write($"{i + 1} ");
        }
        Console.WriteLine("\n长任务完成!");
        return "完成";
    }

    // ----------------------------------------------------------
    // 4. 进度报告
    // ----------------------------------------------------------
    static async Task ProcessWithProgressAsync(IProgress<int> progress)
    {
        for (int i = 0; i <= 100; i += 20)
        {
            await Task.Delay(50);
            progress.Report(i);
        }
    }

    // ----------------------------------------------------------
    // 5. 异步流(IAsyncEnumerable,C# 8.0+)
    // ----------------------------------------------------------
    // 【用途】流式处理大量数据,分批返回而不是一次性加载全部

    static async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
    {
        for (int i = 1; i <= count; i++)
        {
            await Task.Delay(50);  // 模拟逐个生成数据
            yield return i;
        }
    }

    static async Task Main()
    {
        Console.WriteLine("=== async/await 基础 ===");

        // 基本异步调用
        string data = await FetchDataAsync("https://api.example.com");
        Console.WriteLine(data);

        int result = await ComputeAsync(7);
        Console.WriteLine($"7² = {result}");

        // ----------------------------------------------------------
        // 并发执行(同时启动多个任务)
        // ----------------------------------------------------------
        Console.WriteLine("\n=== 并发执行 ===");

        // 错误方式(顺序执行,耗时叠加)
        var sw = System.Diagnostics.Stopwatch.StartNew();
        // var r1 = await FetchDataAsync("url1");  // 等待完成再执行下一个
        // var r2 = await FetchDataAsync("url2");

        // 正确方式(并发执行,任务同时开始)
        var task1 = FetchDataAsync("url1");
        var task2 = FetchDataAsync("url2");
        var task3 = ComputeAsync(10);

        await Task.WhenAll(task1, task2, task3);
        sw.Stop();
        Console.WriteLine($"并发完成:{task1.Result}");
        Console.WriteLine($"并发完成:{task2.Result}");
        Console.WriteLine($"计算结果:{task3.Result}");
        Console.WriteLine($"耗时约 {sw.ElapsedMilliseconds}ms(并发,非顺序叠加)");

        // WhenAny:等待任意一个完成
        Console.WriteLine("\n=== WhenAny ===");
        var tasks = new[]
        {
            Task.Delay(300).ContinueWith(_ => "慢任务"),
            Task.Delay(100).ContinueWith(_ => "快任务"),
            Task.Delay(200).ContinueWith(_ => "中等任务"),
        };
        var first = await Task.WhenAny(tasks);
        Console.WriteLine($"最先完成: {await first}");

        // ----------------------------------------------------------
        // 异常处理
        // ----------------------------------------------------------
        Console.WriteLine("\n=== 异常处理 ===");

        try
        {
            string ok = await FetchWithErrorAsync(false);
            Console.WriteLine($"成功: {ok}");

            string fail = await FetchWithErrorAsync(true);
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"捕获异常: {ex.Message}");
        }

        // 批量任务中的异常处理
        var failingTasks = new[]
        {
            FetchWithErrorAsync(false),
            FetchWithErrorAsync(true),
            FetchWithErrorAsync(false),
        };

        try
        {
            await Task.WhenAll(failingTasks);
        }
        catch (Exception)
        {
            // WhenAll 失败时,所有任务都完成了(包括失败的)
            foreach (var t in failingTasks)
            {
                if (t.IsFaulted)
                    Console.WriteLine($"任务失败: {t.Exception?.InnerException?.Message}");
                else
                    Console.WriteLine($"任务成功: {t.Result}");
            }
        }

        // ----------------------------------------------------------
        // 取消令牌
        // ----------------------------------------------------------
        Console.WriteLine("\n=== 取消令牌 ===");

        using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(350));
        try
        {
            await LongRunningTaskAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("\n任务被取消!");
        }

        // ----------------------------------------------------------
        // 进度报告
        // ----------------------------------------------------------
        Console.WriteLine("\n=== 进度报告 ===");

        var progress = new Progress<int>(percent =>
            Console.Write($"\r进度: {percent}%   "));
        await ProcessWithProgressAsync(progress);
        Console.WriteLine("\n处理完成!");

        // ----------------------------------------------------------
        // 异步流
        // ----------------------------------------------------------
        Console.WriteLine("\n=== 异步流 ===");

        await foreach (int num in GenerateNumbersAsync(5))
        {
            Console.Write($"{num} ");
        }
        Console.WriteLine("(异步流完成)");

        // ----------------------------------------------------------
        // ValueTask(轻量级异步)
        // ----------------------------------------------------------
        Console.WriteLine("\n=== ValueTask ===");
        // 【用途】经常同步完成的方法,避免 Task 的堆分配开销

        static async ValueTask<int> GetCachedValueAsync(bool useCache)
        {
            if (useCache)
                return 42;  // 同步返回,不分配 Task 对象

            await Task.Delay(50);
            return 100;
        }

        int cached = await GetCachedValueAsync(true);
        int computed = await GetCachedValueAsync(false);
        Console.WriteLine($"缓存值: {cached}, 计算值: {computed}");

        Console.WriteLine("\n=== async/await 演示完成 ===");
    }
}

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布