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("操作被取消");
    }
}
相关推荐
Wenweno0o18 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
于慨18 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz18 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶18 小时前
前端交互规范(Web 端)
前端
CHU72903518 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
chenjingming66618 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
GISer_Jing18 小时前
Page-agent MCP结构
前端·人工智能
王霸天18 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航18 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界18 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript