二十八、IO绑定的异步操作是吗?
摘要:📦 第28章:IO 绑定的异步操作(IO-Bound Async) 🧭 目录(你可以先扫一眼) 🌐 Windows IO 模型与 IOCP
📦 第28章:I/O 绑定的异步操作(I/O-Bound Async)
🧭 目录(你可以先扫一眼)
🌐 Windows I/O 模型与 IOCP
🧵 C# async/await 背后的状态机
🧰 常用 I/O 异步 API(FileStream/Socket/HttpClient)
🛑 取消、超时、进度、异常的正确姿势
🧠 ConfigureAwait(false) 与同步上下文
🧪 代码清单(.NET 标准)
🎮 Unity 实战清单(含 UI 更新)
🪤 典型坑位&优化清单
🎯 面试题(5 题带解析)
🌐 1) Windows I/O 模型速写:为啥 I/O 异步“真不占线程”
Windows 的“I/O 完成端口(IOCP)(I/O Completion Ports)”让 I/O 操作在等待阶段不占用任何工作线程:内核驱动硬件;I/O 完成时把“完成事件”投递到完成端口;线程池取事件、调度你的 continuation。
sequenceDiagram
autonumber
participant App as 你的代码
participant CLR as CLR/ThreadPool
participant OS as Windows内核
participant Dev as 设备/网络/磁盘
App->>CLR: Begin I/O(ReadAsync/SendAsync/...)
CLR->>OS: 投递重叠I/O (Overlapped I/O)
Note over OS,Dev: 硬件/驱动进行实际I/O,<br/>中途不占用户线程
OS-->>CLR: I/O完成信号(IOCP队列)
CLR-->>App: 调度继续执行(await之后的代码)
结论:I/O 异步 ≠ 开新线程;等待阶段真正“0 线程占用”。
🧵 2) async/await 究竟干了啥:编译器状态机
async 方法会被编译成一个状态机类,把你的方法拆成若干状态(MoveNext() 驱动),await 处挂起,任务完成后由awaiter 回调继续执行。
flowchart LR
A[进入 async 方法] --> B{遇到 await?}
B -- 否 --> C[同步继续执行]
B -- 是 --> D[注册continuation返回Task]
D --> E[底层I/O完成 IOCP]
E --> F[awaiter 调用 MoveNext]
F --> B
好处:代码“看起来像同步”,却没有阻塞。
🧰 3) 常用 I/O 异步 API 一览
文件:FileStream.ReadAsync/WriteAsync、File.ReadAllTextAsync
网络:Socket.SendAsync/ReceiveAsync、HttpClient.SendAsync
管道/进程:PipeReader.ReadAsync、Process.StandardOutput.ReadToEndAsync
数据库:DbCommand.ExecuteReaderAsync(驱动要支持)
记得给 FileStream 合理的 FileOptions、bufferSize,网络侧关注超时与连接复用。
