多线程之异步编程模型(Async/Await)

1、从生活比喻开始

场景:餐厅的异步服务

  • 同步方式:服务员点完菜后,一直站在厨房门口等待,直到菜做好才服务下一桌

  • 异步方式:服务员点完菜后,继续服务其他客人,厨房做好菜后通知服务员上菜

Async/Await 的本质:一种让异步代码写得像同步代码一样直观的语法糖,底层基于状态机和回调机制实现非阻塞执行。

2、Async/Await 的核心本质

2.1 状态机转换

编译器将 async 方法转换为一个状态机:

// 原始 async 方法
public async Task<int> GetDataAsync()
{
    Console.WriteLine("开始获取数据");
    string data = await DownloadStringAsync("http://example.com");
    int length = data.Length;
    Console.WriteLine($"数据长度: {length}");
    return length;
}

// 编译器生成的状态机(概念性)
class GetDataAsyncStateMachine : IAsyncStateMachine
{
    private int _state = -1;           // 状态标识
    private TaskAwaiter<string> _awaiter; // 等待器
    private string _data;              // 局部变量
    private int _length;               // 局部变量
    public AsyncTaskMethodBuilder<int> _builder; // 任务构建器
    
    void IAsyncStateMachine.MoveNext()
    {
        try
        {
            switch (_state)
            {
                case -1: // 初始状态 - await 之前的部分
                    Console.WriteLine("开始获取数据");
                    
                    // 开始异步操作
                    Task<string> downloadTask = DownloadStringAsync("http://example.com");
                    _awaiter = downloadTask.GetAwaiter();
                    
                    if (!_awaiter.IsCompleted) // 如果操作尚未完成
                    {
                        _state = 0; // 设置下一个状态
                        _awaiter.OnCompleted(MoveNext); // 注册完成回调
                        return; // 退出,让出控制权
                    }
                    // 如果已经完成,直接继续执行
                    goto case 0;
                    
                case 0: // await 完成后的状态
                    _data = _awaiter.GetResult(); // 获取异步结果
                    _length = _data.Length;
                    Console.WriteLine($"数据长度: {_length}");
                    _builder.SetResult(_length); // 设置最终结果
                    break;
            }
        }
        catch (Exception ex)
        {
            _builder.SetException(ex); // 设置异常
        }
    }
    
    void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
    {
        _builder.SetStateMachine(stateMachine);
    }
}

2.2 执行上下文流动`class ExecutionContextFlow

{
public async Task DemonstrateContextFlow()
{
// 执行上下文包含:安全上下文、文化信息、同步上下文等

    Console.WriteLine($"原始线程: {Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine($"原始文化: {Thread.CurrentThread.CurrentCulture}");
    
    // 默认情况下,执行上下文会流动
    await Task.Run(() => {
        Console.WriteLine($"延续线程: {Thread.CurrentThread.ManagedThreadId}");
        Console.WriteLine($"延续文化: {Thread.CurrentThread.CurrentCulture}");
    });
    
    // 使用 ConfigureAwait(false) 禁止上下文流动
    await Task.Run(() => {
        Console.WriteLine("没有上下文流动");
    }).ConfigureAwait(false);
}

}`

3、底层原理深入解析

3.1 等待器(Awaiter)模式

async/await 基于通用的等待器模式,任何实现此模式的对象都可以被 await:

// 可等待模式的概念性定义
public interface IAwaiter<out T> : INotifyCompletion
{
    bool IsCompleted { get; }
    T GetResult();
}

public interface IAwaitable<out T>
{
    IAwaiter<T> GetAwaiter();
}

// Task 的实现
public class Task<T> : IAwaitable<T>
{
    public TaskAwaiter<T> GetAwaiter()
    {
        return new TaskAwaiter<T>(this);
    }
}

public struct TaskAwaiter<T> : IAwaiter<T>
{
    private readonly Task<T> _task;
    
    public TaskAwaiter(Task<T> task)
    {
        _task = task;
    }
    
    public bool IsCompleted => _task.IsCompleted;
    
    public T GetResult()
    {
        return _task.Result; // 阻塞直到任务完成
    }
    
    public void OnCompleted(Action continuation)
    {
        // 注册回调,当任务完成时执行 continuation
        _task.ContinueWith(_ => continuation());
    }
}

3.2 同步上下文(SynchronizationContext)

class SynchronizationContextDemo
{
    // 在 UI 应用程序中的同步上下文
    public async Task UpdateUIAsync()
    {
        // 在 UI 线程执行
        textBox.Text = "开始下载...";
        
        // await 默认会捕获同步上下文
        string data = await DownloadDataAsync();
        
        // 这里会回到原始的 UI 线程执行
        textBox.Text = $"下载完成: {data}";
    }
    
    // 在控制台应用程序中
    public async Task ConsoleAppAsync()
    {
        Console.WriteLine($"开始在线程: {Thread.CurrentThread.ManagedThreadId}");
        
        // 控制台应用没有特殊的同步上下文
        await Task.Delay(1000);
        
        // 可能在任何线程池线程上继续执行
        Console.WriteLine($"继续在线程: {Thread.CurrentThread.ManagedThreadId}");
    }
    
    // 使用 ConfigureAwait 控制上下文流动
    public async Task ConfigureAwaitExample()
    {
        // UI 线程
        textBox.Text = "开始处理...";
        
        // 不捕获上下文,可能在线程池线程继续
        var data = await ProcessDataAsync().ConfigureAwait(false);
        
        // 这里不在 UI 线程,需要手动调度
        this.BeginInvoke(new Action(() => {
            textBox.Text = $"处理完成: {data}";
        }));
    }
}

4、Async/Await 的完整使用

4.1 基础异步操作

class BasicAsyncOperations
{
    // 1. 异步方法签名
    public async Task SimpleAsyncMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine("异步操作完成");
    }
    
    // 2. 返回值的异步方法
    public async Task<int> CalculateAsync(int input)
    {
        await Task.Delay(500);
        return input * 2;
    }
    
    // 3. 异步 void 方法(谨慎使用,主要用于事件处理)
    public async void ButtonClickHandler(object sender, EventArgs e)
    {
        try
        {
            await ProcessClickAsync();
        }
        catch (Exception ex)
        {
            // 必须处理异常,因为 async void 无法被调用者捕获
            Console.WriteLine($"处理点击时出错: {ex.Message}");
        }
    }
    
    // 4. 异步静态方法
    public static async Task<string> GetStaticDataAsync()
    {
        await Task.Delay(200);
        return "静态数据";
    }
    
    public async Task DemonstrateBasicUsage()
    {
        Console.WriteLine("=== 基础异步操作演示 ===\n");
        
        // 1. 等待单个异步操作
        Console.WriteLine("开始等待...");
        await Task.Delay(1000);
        Console.WriteLine("1秒后继续");
        
        // 2. 获取异步结果
        int result = await CalculateAsync(21);
        Console.WriteLine($"计算结果: {result}");
        
        // 3. 连续异步操作
        string data = await FetchDataAsync();
        int length = await ProcessDataAsync(data);
        Console.WriteLine($"处理后的数据长度: {length}");
    }
    
    private async Task<string> FetchDataAsync()
    {
        await Task.Delay(300);
        return "示例数据";
    }
    
    private async Task<int> ProcessDataAsync(string data)
    {
        await Task.Delay(200);
        return data.Length;
    }
    
    private async Task ProcessClickAsync()
    {
        await Task.Delay(100);
    }
}

4.2 异步异常处理

class AsyncExceptionHandling
{
    public async Task DemonstrateExceptionHandling()
    {
        Console.WriteLine("=== 异步异常处理 ===\n");
        
        // 1. 基本的异常处理
        try
        {
            await FaultyAsyncMethod();
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"捕获异常: {ex.Message}");
        }
        
        // 2. 多个异步任务的异常处理
        var task1 = FaultyAsyncMethod("任务1");
        var task2 = FaultyAsyncMethod("任务2");
        
        try
        {
            await Task.WhenAll(task1, task2);
        }
        catch (AggregateException ae)
        {
            Console.WriteLine($"聚合异常包含 {ae.InnerExceptions.Count} 个异常:");
            foreach (var ex in ae.InnerExceptions)
            {
                Console.WriteLine($"  - {ex.Message}");
            }
        }
        
        // 3. 分别处理每个任务的异常
        var task3 = FaultyAsyncMethod("任务3");
        var task4 = FaultyAsyncMethod("任务4");
        
        var allTasks = Task.WhenAll(task3, task4);
        try
        {
            await allTasks;
        }
        catch
        {
            // 检查每个任务的异常状态
            if (task3.IsFaulted)
                Console.WriteLine($"任务3失败: {task3.Exception.InnerException.Message}");
                
            if (task4.IsFaulted)
                Console.WriteLine($"任务4失败: {task4.Exception.InnerException.Message}");
        }
        
        // 4. 超时处理
        try
        {
            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
            await LongRunningOperationAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("操作超时被取消");
        }
    }
    
    private async Task FaultyAsyncMethod(string name = "默认任务")
    {
        await Task.Delay(100);
        throw new InvalidOperationException($"{name} 故意抛出异常");
    }
    
    private async Task LongRunningOperationAsync(CancellationToken cancellationToken)
    {
        for (int i = 0; i < 10; i++)
        {
            cancellationToken.ThrowIfCancellationRequested();
            await Task.Delay(1000, cancellationToken);
            Console.WriteLine($"进行中... {i + 1}/10");
        }
    }
}

4.3 异步组合和并行

class AsyncComposition
{
    public async Task DemonstrateComposition()
    {
        Console.WriteLine("=== 异步组合和并行 ===\n");
        
        // 1. 顺序执行
        Console.WriteLine("1. 顺序执行:");
        var stopwatch = Stopwatch.StartNew();
        
        var result1 = await ProcessStep1Async();
        var result2 = await ProcessStep2Async(result1);
        var finalResult = await ProcessStep3Async(result2);
        
        Console.WriteLine($"顺序执行耗时: {stopwatch.ElapsedMilliseconds}ms");
        Console.WriteLine($"最终结果: {finalResult}");
        
        // 2. 并行执行
        Console.WriteLine("\n2. 并行执行:");
        stopwatch.Restart();
        
        var taskA = ProcessStep1Async();
        var taskB = ProcessStep2Async("预计算值");
        var taskC = ProcessStep3Async(100);
        
        var results = await Task.WhenAll(taskA, taskB, taskC);
        Console.WriteLine($"并行执行耗时: {stopwatch.ElapsedMilliseconds}ms");
        Console.WriteLine($"并行结果: [{string.Join(", ", results)}]");
        
        // 3. 选择第一个完成的任务
        Console.WriteLine("\n3. 选择第一个完成的任务:");
        var fastTask = FastOperationAsync();
        var slowTask = SlowOperationAsync();
        
        var firstCompleted = await Task.WhenAny(fastTask, slowTask);
        Console.WriteLine($"第一个完成的任务结果: {await firstCompleted}");
        
        // 4. 带超时的任务选择
        Console.WriteLine("\n4. 带超时的任务选择:");
        var operationTask = SlowOperationAsync();
        var timeoutTask = Task.Delay(1500);
        
        var completedTask = await Task.WhenAny(operationTask, timeoutTask);
        if (completedTask == operationTask)
        {
            Console.WriteLine($"操作完成: {await operationTask}");
        }
        else
        {
            Console.WriteLine("操作超时");
        }
        
        // 5. 异步 LINQ
        Console.WriteLine("\n5. 异步 LINQ:");
        var numbers = Enumerable.Range(1, 5);
        var processedNumbers = await Task.WhenAll(numbers.Select(ProcessNumberAsync));
        Console.WriteLine($"处理后的数字: [{string.Join(", ", processedNumbers)}]");
    }
    
    private async Task<string> ProcessStep1Async()
    {
        await Task.Delay(300);
        return "步骤1结果";
    }
    
    private async Task<int> ProcessStep2Async(string input)
    {
        await Task.Delay(400);
        return input.Length * 10;
    }
    
    private async Task<string> ProcessStep3Async(int input)
    {
        await Task.Delay(500);
        return $"最终值: {input + 100}";
    }
    
    private async Task<string> FastOperationAsync()
    {
        await Task.Delay(200);
        return "快速操作完成";
    }
    
    private async Task<string> SlowOperationAsync()
    {
        await Task.Delay(2000);
        return "慢速操作完成";
    }
    
    private async Task<int> ProcessNumberAsync(int number)
    {
        await Task.Delay(100);
        return number * number;
    }
}

4.4 高级异步模式

class AdvancedAsyncPatterns
{
    // 1. 异步工厂模式
    public class AsyncResource : IAsyncDisposable
    {
        private AsyncResource() { }
        
        public static async Task<AsyncResource> CreateAsync()
        {
            var resource = new AsyncResource();
            await resource.InitializeAsync();
            return resource;
        }
        
        private async Task InitializeAsync()
        {
            await Task.Delay(1000);
            Console.WriteLine("资源初始化完成");
        }
        
        public async ValueTask DisposeAsync()
        {
            await CleanupAsync();
            Console.WriteLine("资源清理完成");
        }
        
        private async Task CleanupAsync()
        {
            await Task.Delay(500);
        }
    }
    
    // 2. 异步延迟初始化
    private readonly AsyncLazy<ExpensiveResource> _expensiveResource = 
        new AsyncLazy<ExpensiveResource>(async () => {
            var resource = new ExpensiveResource();
            await resource.InitializeAsync();
            return resource;
        });
    
    public async Task UseAsyncLazy()
    {
        var resource = await _expensiveResource;
        await resource.DoSomethingAsync();
    }
    
    // 3. 异步锁模式
    private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
    
    public async Task<string> GetOrCreateAsync(string key)
    {
        // 快速路径:无锁检查
        if (_cache.TryGetValue(key, out string value))
            return value;
        
        // 慢速路径:获取异步锁
        await _asyncLock.WaitAsync();
        try
        {
            // 双重检查
            if (_cache.TryGetValue(key, out value))
                return value;
            
            // 创建新值
            value = await CreateValueAsync(key);
            _cache[key] = value;
            return value;
        }
        finally
        {
            _asyncLock.Release();
        }
    }
    
    // 4. 异步生产者-消费者
    public async Task DemonstrateAsyncProducerConsumer()
    {
        var channel = Channel.CreateBounded<int>(10);
        
        // 生产者
        var producer = Task.Run(async () => {
            for (int i = 0; i < 20; i++)
            {
                await channel.Writer.WriteAsync(i);
                Console.WriteLine($"生产: {i}");
                await Task.Delay(100);
            }
            channel.Writer.Complete();
        });
        
        // 消费者
        var consumer = Task.Run(async () => {
            await foreach (var item in channel.Reader.ReadAllAsync())
            {
                Console.WriteLine($"消费: {item}");
                await Task.Delay(150);
            }
        });
        
        await Task.WhenAll(producer, consumer);
    }
    
    // 5. 取消令牌支持
    public async Task<int> LongRunningOperationWithCancellationAsync(
        CancellationToken cancellationToken = default)
    {
        for (int i = 0; i < 100; i++)
        {
            cancellationToken.ThrowIfCancellationRequested();
            
            await Task.Delay(100, cancellationToken);
            
            // 模拟工作进度
            if (i % 10 == 0)
                Console.WriteLine($"进度: {i}%");
        }
        
        return 42;
    }
    
    // 6. 异步流 (C# 8.0+)
    public async IAsyncEnumerable<int> GenerateAsyncSequence()
    {
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(200);
            yield return i;
        }
    }
    
    public async Task ConsumeAsyncStream()
    {
        await foreach (var number in GenerateAsyncSequence())
        {
            Console.WriteLine($"收到: {number}");
        }
    }
    
    private Dictionary<string, string> _cache = new Dictionary<string, string>();
    
    private async Task<string> CreateValueAsync(string key)
    {
        await Task.Delay(500);
        return $"Value_for_{key}";
    }
}

// 异步延迟初始化类
public class AsyncLazy<T> : Lazy<Task<T>>
{
    public AsyncLazy(Func<Task<T>> taskFactory) : base(taskFactory) { }
    
    public TaskAwaiter<T> GetAwaiter() => Value.GetAwaiter();
}

public class ExpensiveResource
{
    public Task InitializeAsync() => Task.Delay(1000);
    public Task DoSomethingAsync() => Task.Delay(500);
}

4.5 性能优化技巧

class AsyncPerformanceOptimization
{
    // 1. 使用 ValueTask 避免分配
    private Dictionary<int, string> _cache = new Dictionary<int, string>();
    
    public async ValueTask<string> GetCachedValueAsync(int key)
    {
        if (_cache.TryGetValue(key, out string value))
        {
            return value; // 同步返回,不分配 Task
        }
        
        return await FetchValueAsync(key); // 异步操作,分配 Task
    }
    
    // 2. 使用 ConfigureAwait(false)
    public async Task<string> LibraryMethodAsync()
    {
        // 在库代码中,通常不需要回到原始上下文
        var data = await FetchDataAsync().ConfigureAwait(false);
        return ProcessData(data);
    }
    
    // 3. 避免异步包装同步方法
    public Task<int> BadWrapperAsync()
    {
        // 错误:同步方法包装成异步
        return Task.Run(() => ComputeIntensively()); // 不必要地使用线程池
    }
    
    public ValueTask<int> GoodWrapperAsync()
    {
        // 如果可能同步完成,使用 ValueTask
        if (_cache.TryGetValue("result", out int cachedResult))
        {
            return new ValueTask<int>(cachedResult);
        }
        
        return new ValueTask<int>(ComputeAndCacheAsync());
    }
    
    // 4. 批量异步操作
    public async Task<List<string>> ProcessBatchAsync(List<int> ids)
    {
        // 错误:逐个处理
        // var results = new List<string>();
        // foreach (var id in ids)
        // {
        //     results.Add(await ProcessItemAsync(id));
        // }
        
        // 正确:批量处理
        var tasks = ids.Select(id => ProcessItemAsync(id));
        return (await Task.WhenAll(tasks)).ToList();
    }
    
    // 5. 异步方法的热路径优化
    public async ValueTask<string> GetDataOptimizedAsync(int key)
    {
        // 热路径:快速检查
        if (key < 0) 
            return "Invalid";
            
        // 热路径:缓存检查
        if (_cache.TryGetValue(key, out string value))
            return value;
        
        // 冷路径:异步获取
        return await FetchFromSourceAsync(key);
    }
    
    public async Task DemonstratePerformance()
    {
        Console.WriteLine("=== 异步性能优化演示 ===\n");
        
        // 测试 ValueTask 性能
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < 1000; i++)
        {
            _ = await GetCachedValueAsync(i % 10); // 大部分命中缓存
        }
        Console.WriteLine($"ValueTask 测试: {stopwatch.ElapsedMilliseconds}ms");
        
        // 测试批量操作性能
        var ids = Enumerable.Range(1, 100).ToList();
        
        stopwatch.Restart();
        var results1 = await ProcessBatchOneByOneAsync(ids);
        Console.WriteLine($"逐个处理: {stopwatch.ElapsedMilliseconds}ms");
        
        stopwatch.Restart();
        var results2 = await ProcessBatchParallelAsync(ids);
        Console.WriteLine($"批量处理: {stopwatch.ElapsedMilliseconds}ms");
    }
    
    private async Task<string> FetchValueAsync(int key)
    {
        await Task.Delay(10);
        var value = $"Value_{key}";
        _cache[key] = value;
        return value;
    }
    
    private async Task<string> FetchDataAsync()
    {
        await Task.Delay(100);
        return "data";
    }
    
    private string ProcessData(string data) => data.ToUpper();
    
    private int ComputeIntensively()
    {
        Thread.Sleep(100);
        return 42;
    }
    
    private async Task<int> ComputeAndCacheAsync()
    {
        await Task.Delay(100);
        var result = 42;
        _cache["result"] = result;
        return result;
    }
    
    private async Task<string> ProcessItemAsync(int id)
    {
        await Task.Delay(10);
        return $"Processed_{id}";
    }
    
    private async Task<string> FetchFromSourceAsync(int key)
    {
        await Task.Delay(100);
        var value = $"Fetched_{key}";
        _cache[key] = value;
        return value;
    }
    
    private async Task<List<string>> ProcessBatchOneByOneAsync(List<int> ids)
    {
        var results = new List<string>();
        foreach (var id in ids)
        {
            results.Add(await ProcessItemAsync(id));
        }
        return results;
    }
    
    private async Task<List<string>> ProcessBatchParallelAsync(List<int> ids)
    {
        var tasks = ids.Select(id => ProcessItemAsync(id));
        return (await Task.WhenAll(tasks)).ToList();
    }
}

5、Async/Await 的内部工作机制

5.1 状态机执行流程

class StateMachineExecution
{
    // async/await 的完整执行流程:
    public void AsyncMethodExecutionFlow()
    {
        // 1. 调用 async 方法时,同步执行直到第一个 await
        // 2. 如果 await 的操作已经完成,继续同步执行
        // 3. 如果 await 的操作未完成:
        //    a. 方法返回一个未完成的 Task
        //    b. 注册回调,当操作完成时恢复执行
        //    c. 让出当前线程,不阻塞
        // 4. 当操作完成时,回调执行,状态机从 await 之后继续
        // 5. 如果有关联的同步上下文,在原始上下文中恢复
    }
    
    // 状态机的生命周期
    class AsyncStateMachineLifecycle
    {
        // 创建阶段:编译器生成状态机类
        // 初始化阶段:设置初始状态和局部变量
        // 执行阶段:MoveNext() 方法驱动状态流转
        // 完成阶段:设置最终结果或异常
        // 清理阶段:释放资源
    }
}

5.2 线程使用分析

class ThreadUsageAnalysis
{
    public async Task DemonstrateThreadUsage()
    {
        Console.WriteLine($"主线程: {Thread.CurrentThread.ManagedThreadId}");
        
        // I/O 密集型操作 - 不使用线程等待
        await File.ReadAllTextAsync("test.txt");
        Console.WriteLine($"I/O 完成线程: {Thread.CurrentThread.ManagedThreadId}");
        
        // CPU 密集型操作 - 使用线程池线程
        await Task.Run(() => {
            Console.WriteLine($"CPU 工作线程: {Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(1000);
        });
        Console.WriteLine($"CPU 完成线程: {Thread.CurrentThread.ManagedThreadId}");
        
        // Timer 回调 - 使用线程池线程
        await Task.Delay(1000);
        Console.WriteLine($"Timer 完成线程: {Thread.CurrentThread.ManagedThreadId}");
    }
}

6、最佳实践和注意事项

6.1 正确模式

class AsyncBestPractices
{
    // 1. 异步方法命名约定
    public async Task<string> GetDataAsync() { ... } // 正确:Async 后缀
    public async Task<string> GetData() { ... }      // 避免:缺少 Async 后缀
    
    // 2. 避免 async void(除了事件处理程序)
    public async Task MethodAsync() { ... }          // 正确
    public async void BadMethod() { ... }            // 避免
    
    // 3. 合理使用 ConfigureAwait
    public async Task<string> LibraryCodeAsync()
    {
        // 在库代码中通常使用 ConfigureAwait(false)
        var data = await FetchDataAsync().ConfigureAwait(false);
        return ProcessData(data);
    }
    
    public async Task UI CodeAsync()
    {
        // 在UI代码中通常需要回到UI线程
        var data = await FetchDataAsync(); // 默认捕获上下文
        UpdateUI(data);
    }
    
    // 4. 避免在异步方法中阻塞
    public async Task<string> GoodPatternAsync()
    {
        return await GetDataAsync(); // 正确:使用 await
    }
    
    public string BadPattern()
    {
        return GetDataAsync().Result; // 错误:可能导致死锁
    }
    
    // 5. 正确处理取消
    public async Task<int> ProcessWithCancellationAsync(
        CancellationToken cancellationToken = default)
    {
        await Task.Delay(1000, cancellationToken);
        cancellationToken.ThrowIfCancellationRequested();
        return 42;
    }
    
    // 6. 异步初始化模式
    private Task _initializationTask;
    public Task EnsureInitializedAsync()
    {
        return _initializationTask ??= InitializeAsync();
    }
    
    private async Task InitializeAsync()
    {
        await Task.Delay(1000);
    }
}

6.2 常见陷阱

class AsyncPitfalls
{
    // 1. 死锁:在同步上下文中阻塞等待异步方法
    public void DeadlockExample()
    {
        // 在 UI 线程中调用会导致死锁
        // var result = GetDataAsync().Result;
        
        // 解决方案:使用 async/await 贯穿始终
        // 或者使用 ConfigureAwait(false)
    }
    
    // 2. 忘记 await
    public async Task ForgetAwaitExample()
    {
        // 错误:忘记 await,异常可能被忽略
        // ProcessDataAsync(); // 没有 await
        
        // 正确:
        await ProcessDataAsync();
    }
    
    // 3. 异常处理不当
    public async void AsyncVoidException()
    {
        // async void 中的异常无法被调用者捕获
        throw new InvalidOperationException("这会崩溃应用程序");
    }
    
    // 4. 过度并行化
    public async Task OverParallelization()
    {
        // 错误:同时启动太多任务
        // var tasks = Enumerable.Range(0, 10000).Select(_ => Task.Run(...));
        
        // 正确:使用适当的并行度控制
        var options = new ParallelOptions { MaxDegreeOfParallelism = 10 };
        await Parallel.ForEachAsync(Enumerable.Range(0, 1000), options, async (i, ct) => {
            await ProcessItemAsync(i);
        });
    }
    
    // 5. 混合同步和异步代码
    public async Task MixedSyncAsync()
    {
        // 错误:在异步方法中同步阻塞
        // Thread.Sleep(1000);
        
        // 正确:使用异步等待
        await Task.Delay(1000);
    }
    
    private async Task ProcessDataAsync()
    {
        await Task.Delay(100);
    }
    
    private async Task ProcessItemAsync(int item)
    {
        await Task.Delay(10);
    }
}

7、总结

Async/Await 的本质:

  • 基于状态机的语法糖,将异步回调转换为同步书写风格

  • 使用续体传递风格(CPS) 实现非阻塞等待

  • 依赖任务等待器模式 实现通用异步操作

核心优势:

  1. 代码简洁:像同步代码一样直观易读

  2. 非阻塞:在等待时不占用线程,提高资源利用率

  3. 可组合:轻松组合多个异步操作

  4. 异常安全:自然的异常处理机制

关键技术点:

  • async:标记方法为异步,启用编译器转换

  • await:等待异步操作完成,让出控制权

  • Task/Task<T>:表示异步操作

  • ValueTask:性能优化的轻量级任务

  • ConfigureAwait:控制同步上下文流动

  • CancellationToken:支持取消操作

使用要点:

  • 异步方法命名以 Async 结尾

  • 避免 async void(除事件处理程序外)

  • 在库代码中考虑使用 ConfigureAwait(false)

  • 避免在异步方法中阻塞

  • 妥善处理异步异常

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值