C# 异步方法

先用几个例子展示这个语法糖的优势

复制代码
public async Task<bool> ComplexBusinessFlow_Clean(int orderId)
{
    try
    {
        // 1. 验证订单
        var validation = await orderService.ValidateOrderAsync(orderId);
        if (!validation.IsValid)
            return false;
        
        // 2. 处理支付
        var paymentResult = await paymentService.ProcessPaymentAsync(orderId);
        if (!paymentResult.Success)
            return false;
        
        // 3. 更新库存
        await inventoryService.UpdateStockAsync(orderId);
        
        // 4. 发送确认邮件
        await emailService.SendConfirmationAsync(orderId);
        
        Console.WriteLine("业务流程完成");
        return true;
    }
    catch (Exception ex)
    {
        logger.LogError(ex, $"订单 {orderId} 处理失败");
        return false;
    }
}
执行顺序分析

// 1. 验证订单 - 第一步 var validation = await

orderService.ValidateOrderAsync(orderId);

// 2. 处理支付 - 第二步(必须等第一步完成) var paymentResult = await paymentService.ProcessPaymentAsync(orderId);

// 3. 更新库存 - 第三步(必须等第二步完成) await inventoryService.UpdateStockAsync(orderId);

// 4. 发送确认邮件 - 第四步(必须等第三步完成) await emailService.SendConfirmationAsync(orderId);

关键特性 //用写同步代码的风格达到了异步执行的效果
  1. 顺序执行 :每个 await都会等待前一个异步操作完成后再执行下一个

  2. 非阻塞:虽然顺序执行,但不会阻塞线程(在等待时可以处理其他任务)

  3. 异常处理统一的 try-catch块确保任何步骤出错都会进入异常处理

    private async void btnLoadData_Click(object sender, EventArgs e)
    {
    try
    {
    progressBar.Visible = true;
    btnLoad.Enabled = false;

    复制代码
         // ✅ 异步等待,不阻塞UI线程
         var data = await httpClient.GetStringAsync(url);
         
         // 自动回到UI线程上下文
         textBox.Text = data;
     }
     catch (Exception ex)
     {
         MessageBox.Show($"加载失败: {ex.Message}");
     }
     finally
     {
         progressBar.Visible = false;
         btnLoad.Enabled = true;
     }

    }

来详细分析这段代码的执行顺序和执行所在线程:

执行顺序分析

  1. 用户点击按钮​ → UI线程

  2. 执行同步代码段

    • progressBar.Visible = true→ UI线程

    • btnLoad.Enabled = false→ UI线程

  3. 遇到await表达式

    • 启动GetStringAsync()异步操作 → 后台线程

    • 方法在此暂停控制权返回给调用者

  4. 异步操作完成后

    • 自动回到UI线程上下文

    • 继续执行await后面的代码

  5. 更新UI

    • textBox.Text = data→ UI线程
  6. 异常处理/清理

    • catch或finally块 → UI线程

线程切换示意图

UI线程: [点击] → [显示进度条] → [禁用按钮] → [暂停等待] → [恢复] → [更新文本框] → [隐藏进度条] ↓ 后台线程: [HTTP请求执行]...

关键线程信息

代码段 执行线程 说明
progressBar.Visible = true UI线程 同步执行
btnLoad.Enabled = false UI线程 同步执行
await httpClient.GetStringAsync() 后台线程池 I/O完成端口线程
textBox.Text = data UI线程 自动回到原始上下文
finally块中的代码 UI线程 同步执行

重要特性

  1. 不会阻塞UI:await期间UI线程可以处理其他消息

  2. 自动线程上下文恢复:await完成后自动回到UI线程

  3. 异常处理安全:任何异常都会在UI线程的catch块中处理

取消操作

使用 CancellationToken

复制代码
public async Task<string> DownloadWithCancelAsync(string url, 
    CancellationToken cancellationToken = default)
{
    using var client = new HttpClient();
    
    // 传递取消令牌
    HttpResponseMessage response = await client.GetAsync(url, cancellationToken);
    response.EnsureSuccessStatusCode();
    
    return await response.Content.ReadAsStringAsync();
}

// 使用示例
public static async Task Main()
{
    var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // 5秒后取消
    
    try
    {
        var result = await DownloadWithCancelAsync("https://example.com", cts.Token);
        Console.WriteLine(result);
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("操作被取消");
    }
}
相关推荐
tyro曹仓舒1 小时前
干了10年前端,才学会使用IntersectionObserver
前端·javascript
lsx2024061 小时前
ionic 模态窗口:深入解析与最佳实践
开发语言
q***13612 小时前
史上最厉害的Java进阶之路
java·开发语言
万事可爱^2 小时前
GitHub爆火开源项目——RustScan深度拆解
c语言·开发语言·rust·开源·github·rustscan
S***y3962 小时前
前端微前端框架对比,qiankun与icestark
前端·前端框架
ekkcole2 小时前
java word转pdf工具类,兼容linux和windows服务器
开发语言·pdf·c#
任子菲阳2 小时前
学Java第四十五天——不可变集合、Stream流
java·开发语言·windows
Wect2 小时前
学习React-DnD:实现多任务项拖拽-useDrop处理
前端·react.js
CodeCraft Studio2 小时前
Excel处理控件Aspose.Cells教程:使用Python从Excel工作表中删除数据透视表
开发语言·python·excel·aspose·aspose.cells·数据透视表