同步(Synchronous)和异步(Asynchronous)

上一篇多线程

C#多线程-CSDN博客

同步特点

  • 代码按顺序执行,一个操作完成后才会执行下一个。
  • 阻塞当前线程,直到操作完成(例如:I/O、网络请求、计算等)。
  • 简单直观,但可能导致性能问题(例如:UI冻结、服务器吞吐量低等)。
cs 复制代码
using System.Net.Http;
using System.Threading.Tasks;

public string GetWebsiteContentSync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        return client.GetStringAsync(url).Result; // 这里使用.Result会导致同步等待
    }
}

异步特点

  • 非阻塞执行,允许在等待操作完成时释放当前线程去做其他工作。
  • 提高响应性(如UI不冻结)和吞吐量(如服务器处理更多请求)。
  • 通过Async/await关键字实现,依赖Task或Taks<T>类型。
cs 复制代码
public async Task<string> GetWebsiteContentAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        return await client.GetStringAsync(url); // 使用await进行异步等待
    }
}
async/await
  • `async`:标记方法为异步方法,方法内可使用`await`。
  • `await`:挂起当前方法,直到异步操作完成,期间线程可被释放去做其他任务。
  • 异步方法应返回`Task`、`Task<T>`或`ValueTask(高性能场景)`。
Task 和 Task<T>
  • Task:表示一个异步操作,可能无返回值。
  • Task<T>:表示返回类型为 `T` 的异步操作。
  • 使用 Task.Run 可将同步代码包装为异步(慎用,避免滥用线程池)。

异步编程最佳实践

避免阻塞异步代码
  • ❌ 不要使用 .Result 或 .Wait(),可能导致死锁。
  • ✅ 始终使用 await:
cs 复制代码
// 正确方式
var result = await SomeAsyncMethod();
异常处理

异步方法中的异常会被包装到Task中,可通过try/catch捕捉:

cs 复制代码
try
{
    await SomeAsyncMethod();
}
catch (Exception ex)
{
    // 处理异常
}
配置上下文

在库代码中使用ConfigureAwait(false)避免上下文切换:

cs 复制代码
var data = await SomeAsyncMethod().ConfigureAwait(false);
避免 async void

仅限事件处理程序(如:按钮点击),否则异常会导致进程崩溃:

cs 复制代码
private async void Button_Click(object sender, EventArgs e)
{
    await SomeAsyncMethod();
}

同步和异步使用场景

场景 同步 异步
UI 响应性(如 WinForms、WPF) ❌ 导致界面冻结 ✅ 保持界面流畅
服务端处理(如 ASP.NET ❌ 吞吐量低 ✅ 高并发处理
I/O 密集型操作(文件、网络) ❌ 阻塞线程 ✅ 释放线程
CPU 密集型计算 ✅ 直接执行 ❌ 需配合 Task.Run
常见误区
  1. 虚假异步:方法标记为 `async` 但内部无 `await`(编译器警告)。

  2. 死锁:在同步上下文中调用 `.Result` 或 `.Wait()`。

  3. 过度异步化:滥用 `Task.Run` 包装同步代码,增加线程切换开销。

总结

  • 同步:简单但阻塞,适合快速完成的操作。
  • 异步:非阻塞且高效,适合 I/O 或高延迟操作。
  • 始终遵循 async/await 模式,避免阻塞调用,合理处理异常和上下文。
相关推荐
djarmy1 小时前
MAIN.c(1): warning C318: can’t open file ‘STC8G.H’ 报错 解决 分析
c语言·开发语言·mongodb
HEJOO91 小时前
深入理解 Java volatile 关键字:原理、用法与常见误区
java·开发语言·spring
曹牧1 小时前
Java:no content to map due to end of input
java·开发语言
梦梦代码精1 小时前
《回收租赁系统技术选型避坑指南:业务闭环与二开自由度详解》
开发语言·低代码·docker·开源·代码规范
隔窗听雨眠2 小时前
记一次SQL Server数据库性能分析:从CPU100%到单配置修复的完整诊断
开发语言·数据库·php
David猪大卫2 小时前
【C++修炼】智能指针使用及原理
开发语言·c++·经验分享·笔记·学习·考研·面试
charlie1145141912 小时前
现代Qt开发之图像处理进阶:像素操作与格式转换
开发语言·图像处理·qt
李永奉2 小时前
中科蓝讯SDK开发-BT893x 面条耳机连接vivo手机后连接APP端,最后手机端设置页面手动断开蓝牙连接,此时耳机端假断开
c语言·开发语言·嵌入式硬件·物联网·智能手机·电脑
秦老师Q3 小时前
php零基础入门到实战,从语法到框架,一篇搞定
开发语言·php
驭渊的小故事3 小时前
多线程02
java·开发语言·jvm