核心概念:非阻塞是什么?
假设你需要从 3 个传感器各读取一次数据,每次读需要 2 秒。
同步(阻塞)方式
读 Sensor1(等 2s)→ 读 Sensor2(等 2s)→ 读 Sensor3(等 2s)
总耗时 = 6 秒,等待期间调用方被"卡住"
总耗时 = 6 秒,等待期间调用方被"卡住"
异步(非阻塞)方式
同时启动 Sensor1 + Sensor2 + Sensor3,三个并行读
总耗时 ≈ 2 秒,等待期间调用方可以做别的事
总耗时 ≈ 2 秒,等待期间调用方可以做别的事
非阻塞的本质:启动一个耗时操作后,不等它完成,把控制权还回去,等操作完成后再回来拿结果。这和 LabVIEW 的数据流模型本身就已经是"并行"的有微妙差异——LabVIEW 中只要两个节点没有数据依赖,它们天然并行;而 C# 需要显式用 async/await 来表达"这里可以并行"。
C# 方案:async + await 两个关键字
async+await
// 异步方法:有 async,返回 Task<T>
static async Task<double> ReadSensorAsync(string name)
{
Console.WriteLine($" [{name}] 开始采集...");
await Task.Delay(2000); // 模拟 2 秒采集时间(非阻塞)
return 20 + Random.Shared.NextDouble() * 10;
}
// 调用:用 await 等结果
double result = await ReadSensorAsync("Temp-01");await 就像 LabVIEW 中 Wait on Asynchronous Call 节点——代码暂停在这里,等异步操作返回结果后继续。
“关键区分:Task.Delay(2000) 对线 await = 不阻塞线程。如果用 Thread.Sleep(2000),线程会被卡死 2 秒什么也干不了。”
异步操作中,取消和超时也是标准功能:
取消与超时
// CancellationToken:发出"停止"信号
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try
{
string data = await FetchWithTimeoutAsync(url, cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("请求超时,已取消");
}在 LabVIEW 中这通常需要额外的一个 User Event 或全局 Stop 布尔变量在各个并行 While Loop 之间传递"停止"信号。C# 的 CancellationToken 把这个模式内建到了语言和标准库层面。
C#应用场景:并行多个任务
下方是 async/await 常见的场景:同时启动多个任务,等全部完成:
并行任务
// 启动 3 个任务(它们会同时跑)
Task<double> t1 = ReadSensorAsync("传感器1");
Task<double> t2 = ReadSensorAsync("传感器2");
Task<double> t3 = ReadSensorAsync("传感器3");
// 等全部完成(总时间 = 最慢的那个,不是三个之和)
double[] results = await Task.WhenAll(t1, t2, t3);
// results[0] = 传感器1 的结果
// results[1] = 传感器2 的结果
// results[2] = 传感器3 的结果Task.WhenAll 对标 LabVIEW 中:把 3 个异步 CBR 的引用都拿到手,然后依次 Wait on Async Call。总耗时是 3 个任务中最长的那一个,不是三者之和。
获取执行最快的任务
// 谁先完成用谁的结果
Task<double> winner = await Task.WhenAny(t1, t2, t3);
// winner 就是最先完成的那个任务完整对比表
| 特性 | LabVIEW | C# async/await |
|---|---|---|
| 声明异步操作 | 不需要声明,但一般建议设置 VI 为 Reentrant | async Task<T> Method() |
| 等待结果 | Wait on Asynchronous Call 节点 | await task |
| 并行多个任务 | 多个 CBR 同时 Start,依次 Wait | await Task.WhenAll(t1,t2,t3) |
| 谁先完成用谁 | 手动比较各 CBR 的完成状态 | await Task.WhenAny(t1,t2,t3) |
| 取消 | 全局 Stop 布尔 + 各 Loop 判断 | CancellationToken |
| 超时 | 额外的超时定时器 + 比较 | CancellationTokenSource(TimeSpan) |
| 异常处理 | Error Cluster 线串联 | try-catch 包住 await |
| 异步通信 | Notifier / Queue | Channel<T> / BlockingCollection<T> |
| UI 不卡死 | Event Structure 天然不卡 | UI 线程 await 不阻塞 UI |