[C#] async和await(腾讯元宝)

发布于:2025-05-12 ⋅ 阅读:(10) ⋅ 点赞:(0)

在 C# 中,async 和 await 主要用于编写​​非阻塞异步代码​​,提升程序的响应性和资源利用率。

执行I/O密集型操作,比如文件读写、网络请求或者数据库访问。这些操作通常会等待外部资源,使用异步可以释放线程池线程,提高应用程序的响应性。比如说,如果一个Web服务器处理很多请求,同步方法会导致线程被阻塞,而异步可以让线程处理其他请求,提升吞吐量。

还有UI应用程序,比如WPF或WinForms,长时间运行的任务如果不异步,会导致界面卡顿。使用async可以让后台任务运行,同时保持UI响应。例如,下载文件时,如果同步下载,用户界面就会冻结,但异步的话用户还能操作界面。

应用场景:

适用场景​​:涉及等待外部资源(不占用 CPU 时间)的操作,如:

  • 文件读写(FileStream.ReadAsync
  • 网络请求(HTTP API 调用、数据库查询)
  • 流处理(如图片加载)

异步操作会释放调用线程(如 UI 线程或线程池线程),避免阻塞。例如,Web 服务器通过异步处理可同时服务更多请求。

public async Task<string> DownloadDataAsync()
{
    using var client = new HttpClient();
    return await client.GetStringAsync("https://example.com"); // 非阻塞等待
}

2. 保持 UI 响应性​

​适用场景​​:在桌面或移动应用的 UI 线程中执行耗时操作时(如按钮点击事件)。
异步操作防止界面冻结。例如,文件下载期间用户仍可交互。

private async void DownloadButton_Click(object sender, EventArgs e)
{
    StatusLabel.Text = "Downloading...";
    await Task.Delay(3000); // 模拟耗时操作(如下载)
    StatusLabel.Text = "Done!"; // UI 更新自动回到主线程
}

3. 后端服务高并发​

​适用场景​​:服务器应用(如 ASP.NET Core)处理大量并发请求。
异步方法释放线程池线程,使服务器能处理更多请求,避免线程饥饿。

public async Task<IActionResult> GetData()
{
    var data = await _dbContext.Users.FromSqlRawAsync("SELECT ..."); // 异步数据库查询
    return Ok(data);
}

4. CPU 密集型操作的特殊处理​

​适用场景​​:长时间运行的计算任务(如图像处理、复杂算法)。
需结合 Task.Run 将 CPU 工作转移到线程池,避免阻塞主线程(尤其在 UI 应用中)。

public async Task ProcessImageAsync()
{
    await Task.Run(() => 
    {
        // 耗时的 CPU 计算
        ApplyFilter(image);
    });
    // 回到 UI 线程更新结果
}

何时不需要用 async​

  • ​简单/同步操作​​:纯内存操作(如循环、数学计算)无需异步。
  • ​强制要求同步的 API​​:某些旧库或框架可能不支持异步。

​关键原则​

  1. ​从顶层开始​​:入口点(如 Main、控制器 Action)支持 async(C# 7.1+)。
  2. ​避免 async void​:仅限事件处理,优先用 Task 返回值以便错误处理。
  3. ​注意异常传播​​:异步方法异常会被封装在 AggregateException 或直接抛出(取决于调用方式)。
  4. ​不要滥用 ConfigureAwait(false)​:在库代码中可减少上下文切换开销,但 UI 应用需保留上下文。

网站公告

今日签到

点亮在社区的每一天
去签到