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("操作被取消");
    }
}
相关推荐
ITMr.罗1 分钟前
深入理解EF Core更新机制(开发中因为省事遇到的问题)
服务器·数据库·c#·.net
用户4488466710602 分钟前
.NET进阶——深入理解委托(3)事件入门
c#·.net
世转神风-13 分钟前
qt-pro文件名词解释
开发语言·qt
珑墨19 分钟前
【迭代器】js 迭代器与可迭代对象终极详解
前端·javascript·vue.js
Fantastic_sj27 分钟前
[代码例题] var 和 let 在循环中的作用域差异,以及闭包和事件循环的影响
开发语言·前端·javascript
HashTang1 小时前
【AI 编程实战】第 3 篇:后端小白也能写 API:AI 带我 1 小时搭完 Next.js 服务
前端·后端·ai编程
三年三月1 小时前
React 中 CSS Modules 详解
前端·css
粉末的沉淀1 小时前
tauri:关闭窗口后最小化到托盘
前端·javascript·vue.js
weixin_462446231 小时前
EasyExcel 动态修改模板 Sheet 名称:自定义 SheetWriteHandler 拦截器
java·开发语言·easyexcel
赵庆明老师1 小时前
NET 使用SmtpClient 发送邮件
java·服务器·前端