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("操作被取消");
    }
}
相关推荐
一条咸鱼_SaltyFish21 小时前
远程鉴权中心设计:HTTP 与 gRPC 的技术决策与实践
开发语言·网络·网络协议·程序人生·http·开源软件·个人开发
我即将远走丶或许也能高飞1 天前
vuex 和 pinia 的学习使用
开发语言·前端·javascript
沐知全栈开发1 天前
SQL LEN() 函数详解
开发语言
钟离墨笺1 天前
Go语言--2go基础-->基本数据类型
开发语言·前端·后端·golang
爱吃泡芙的小白白1 天前
Vue 3 核心原理与实战:从响应式到企业级应用
前端·javascript·vue.js
小郭团队1 天前
1_7_五段式SVPWM (传统算法反正切+DPWM3)算法理论与 MATLAB 实现详解
开发语言·嵌入式硬件·算法·matlab·dsp开发
卓怡学长1 天前
m115乐购游戏商城系统
java·前端·数据库·spring boot·spring·游戏
C+-C资深大佬1 天前
C++风格的命名转换
开发语言·c++
No0d1es1 天前
2025年粤港澳青少年信息学创新大赛 C++小学组复赛真题
开发语言·c++
点云SLAM1 天前
C++内存泄漏检测之手动记录法(Manual Memory Tracking)
开发语言·c++·策略模式·内存泄漏检测·c++实战·new / delete