如何让DAwaiter持续检测公共变量值?支持多变量条件吗?
问题描述
需要实现一个DAwaiter方法,持续检测已实例化对象的特定公共bool变量值,直到变量变为指定值(或满足组合条件),而非传递变量副本。当前实现中DAwaiter仅获取变量初始值,无法响应后续变化,同时希望该方法能支持多变量组合条件(如XDone && YDone == true)。
解决方案
1. 实现持续检测单个变量
核心问题是直接传递bool值会产生值类型副本,导致DAwaiter无法获取变量的最新状态。改用Func<bool>委托可以解决这个问题——委托会在每次检查时重新执行lambda表达式,从而获取目标变量的实时值。
修改后的DAwaiter方法:
internal bool DAwaiter(Func<bool> condition, int delay, CancellationToken ct) { Logger("Beginning DAwaiter"); while (!condition()) { Logger($"awaiting... Current state: {condition()}"); if (ct.IsCancellationRequested) { Logger("Cancelled DAwaiter."); return false; } Thread.Sleep(delay); } Logger("DAwaiter finished true."); return true; }
调用单个变量时,传入获取变量的lambda表达式:
// 等待Homed变为true if (!DAwaiter(() => Homed, 250, cts.Token)) { return; }
2. 扩展支持多变量组合条件
由于使用了Func<bool>委托,无需修改DAwaiter方法,直接传入组合条件的lambda表达式即可:
// 等待XDone和YDone同时为true if (!DAwaiter(() => XDone && YDone, 250, cts.Token)) { return; }
完整关键代码示例
public class ArduinoComms { // ... 原有成员变量、SerialPort初始化等代码 ... public void Home() { Homed = false; Ready = false; XDone = false; YDone = false; Logger("Beginning home"); //WriteMyCommand(2); 发送归位命令到Arduino if (!DAwaiter(() => Homed, 250, cts.Token)) { return; } Logger("finished home, beginning backoff"); XDone = false; YDone = false; //WriteMyCommand(0, backoff); //WriteMyCommand(1, backoff); if (!DAwaiter(() => XDone && YDone, 250, cts.Token)) { return; } Logger("Finished home"); Ready = true; } internal bool DAwaiter(Func<bool> condition, int delay, CancellationToken ct) { Logger("Beginning DAwaiter"); while (!condition()) { Logger($"awaiting... Current state: {condition()}"); if (ct.IsCancellationRequested) { Logger("Cancelled DAwaiter."); return false; } Thread.Sleep(delay); } Logger("DAwaiter finished true."); return true; } // ... 原有DataReceived事件处理、Logger等代码 ... }
额外优化建议
如果涉及UI线程,Thread.Sleep会阻塞线程,建议改用异步版本的等待方法,避免UI卡顿:
internal async Task<bool> DAwaiterAsync(Func<bool> condition, int delay, CancellationToken ct) { Logger("Beginning DAwaiter"); while (!condition()) { Logger($"awaiting... Current state: {condition()}"); if (ct.IsCancellationRequested) { Logger("Cancelled DAwaiter."); return false; } await Task.Delay(delay, ct); } Logger("DAwaiter finished true."); return true; }
调用时需将Home改为异步方法:
public async Task Home() { // ... 原有初始化代码 ... if (!await DAwaiterAsync(() => Homed, 250, cts.Token)) { return; } // ... 后续逻辑 ... }
内容的提问来源于stack exchange,提问作者Cameron Hadland
相关产品推荐
相关产品推荐

