上位机硬件状态判断
提供一个方法(例如 WaitForPowerStatus),让其他模块(如电压设置)可以通过循环等待 CanExecutePSRead = true 来决定是否继续。在设置电压的地方(或其他需要等待的地方),可以通过循环等待 CanExecutePSRead = true 来决定是否跳出等待并执行后续操作(如设置电压)。只有当硬件读取状态为 true 且设置状态不为 false 时,CanExec
优化之前的代码,将 GlobalCache.TestPowerReadStatus 和 GlobalCache.TestPowerSetStatus 合并为一个公共状态(例如 GlobalCache.CanExecutePSRead),以简化状态管理,并满足以下要求:
-
统一状态控制:
-
使用一个公共状态变量(CanExecutePSRead)来控制 PSRead 的执行。
-
该状态基于硬件读取状态(AUXRealTimeState1.TestPowerStatus)和设置状态(AUXInsMap["TestPowerSet"])的组合逻辑:
-
只有当硬件读取状态为 true 且设置状态不为 false 时,CanExecutePSRead = true,允许 PSRead。
-
一旦设置状态为 false,CanExecutePSRead 立即变为 false,禁止 PSRead。
-
-
-
循环等待:
-
在设置电压的地方(或其他需要等待的地方),可以通过循环等待 CanExecutePSRead = true 来决定是否跳出等待并执行后续操作(如设置电压)。
-
-
优化目标:
-
简化状态管理,减少多个状态变量的维护成本。
-
确保线程安全,防止多线程环境下状态冲突。
-
支持循环等待机制,便于其他模块(如电压设置)使用。
-
保持日志记录,便于调试。
-
问题:
-
当前代码使用两个状态变量(TestPowerReadStatus 和 TestPowerSetStatus),管理复杂且容易出错。
-
PSRead 的调用条件需要明确检查两个状态,逻辑分散。
-
没有提供循环等待 CanExecutePSRead = true 的机制,用于其他操作(如设置电压)。
优化方案
-
引入公共状态变量:
-
使用 GlobalCache.CanExecutePSRead 作为统一的状态变量,替代 TestPowerReadStatus 和 TestPowerSetStatus。
-
CanExecutePSRead 的值由 UpdatePowerStatus 方法根据 AUXRealTimeState1.TestPowerStatus 和 AUXInsMap["TestPowerSet"] 计算:
-
CanExecutePSRead = AUXRealTimeState1.TestPowerStatus && Convert.ToBoolean(AUXInsMap["TestPowerSet"])
-
-
-
统一状态更新:
-
在 AUXSET 和 Read 方法中调用公共的 UpdatePowerStatus 方法,更新 CanExecutePSRead。
-
确保 AUXSET 设置 false 时,CanExecutePSRead 立即变为 false。
-
-
循环等待机制:
-
提供一个方法(例如 WaitForPowerStatus),让其他模块(如电压设置)可以通过循环等待 CanExecutePSRead = true 来决定是否继续。
-
-
线程安全:
-
使用 lock 保护 GlobalCache.CanExecutePSRead 的读写操作。
-
确保等待机制在多线程环境下安全。
-
-
日志记录:
-
记录状态变化和等待情况,便于调试。
-
优化后的代码
以下是优化后的完整代码,包含统一的公共状态管理和循环等待机制:
csharp
private readonly object _lock = new object(); // 用于线程安全
// 更新公共状态
private void UpdatePowerStatus()
{
lock (_lock)
{
var readStatus = AUXRealTimeState1.TestPowerStatus; // 硬件读取状态
var setStatus = Convert.ToBoolean(AUXInsMap["TestPowerSet"]); // 设置状态
GlobalCache.CanExecutePSRead = readStatus && setStatus; // 只有两者都为 true 时才允许 PSRead
Console.WriteLine($"UpdatePowerStatus: ReadStatus={readStatus}, SetStatus={setStatus}, CanExecutePSRead={GlobalCache.CanExecutePSRead}");
}
}
// AUXSET 方法:响应设置状态变化
public void AUXSET()
{
lock (_lock)
{
UpdatePowerStatus();
}
}
// Read 方法:持续监控硬件状态
public void Read()
{
while (!m_Dis)
{
lock (_lock)
{
UpdatePowerStatus();
}
Thread.Sleep(100); // 保留 100ms 轮询
}
}
// PSRead 调用逻辑
public void ExecutePSRead()
{
lock (_lock)
{
if (GlobalCache.CanExecutePSRead)
{
MingShengInterop.LabVIEWExports.PSRead(HWSelect,
out pSRealV,
out pSRealI,
out PSStatus,
out Error,
out dutRealV);
Console.WriteLine("PSRead executed");
}
else
{
Console.WriteLine($"PSRead skipped: CanExecutePSRead={GlobalCache.CanExecutePSRead}");
}
}
}
// 循环等待 CanExecutePSRead 为 true(例如用于设置电压)
public bool WaitForPowerStatus(int timeoutMs = 5000, int pollIntervalMs = 100)
{
var startTime = DateTime.Now;
while ((DateTime.Now - startTime).TotalMilliseconds < timeoutMs)
{
lock (_lock)
{
if (GlobalCache.CanExecutePSRead)
{
Console.WriteLine("WaitForPowerStatus: CanExecutePSRead is true, exiting wait");
return true;
}
}
Console.WriteLine("WaitForPowerStatus: Waiting...");
Thread.Sleep(pollIntervalMs); // 每 100ms 检查一次
}
Console.WriteLine($"WaitForPowerStatus: Timeout after {timeoutMs}ms");
return false; // 超时未达到 true
}
// 示例:设置电压时等待 CanExecutePSRead 为 true
public void SetVoltage()
{
if (WaitForPowerStatus(timeoutMs: 5000)) // 等待最多 5 秒
{
// 执行电压设置逻辑
Console.WriteLine("SetVoltage: Power status is ready, setting voltage...");
// 例如:CallVoltageSetFunction();
}
else
{
Console.WriteLine("SetVoltage: Failed to set voltage due to timeout or invalid power status");
}
}
优化点说明
-
统一状态管理:
-
引入 GlobalCache.CanExecutePSRead 作为公共状态变量,基于 AUXRealTimeState1.TestPowerStatus 和 AUXInsMap["TestPowerSet"] 的逻辑与(&&)计算。
-
UpdatePowerStatus 方法统一更新状态,确保:
-
当硬件读取状态为 true 且设置状态为 true 时,CanExecutePSRead = true。
-
当设置状态为 false 或硬件读取状态为 false 时,CanExecutePSRead = false。
-
-
这满足“读取为真才可以 PSRead,一设置为 false 就停止”的需求。
-
-
循环等待机制:
-
新增 WaitForPowerStatus 方法,允许其他模块(如电压设置)等待 CanExecutePSRead = true。
-
参数:
-
timeoutMs:最大等待时间(默认 5000ms,即 5 秒)。
-
pollIntervalMs:轮询间隔(默认 100ms,与 Read 方法一致)。
-
-
返回 true 表示状态变为 true,返回 false 表示超时。
-
示例中,SetVoltage 方法调用 WaitForPowerStatus 等待状态就绪后再设置电压。
-
-
线程安全:
-
所有状态访问(CanExecutePSRead)和更新(UpdatePowerStatus)都使用 lock (_lock),确保多线程安全。
-
WaitForPowerStatus 和 ExecutePSRead 也加锁,避免状态冲突。
-
-
日志记录:
-
记录 UpdatePowerStatus 的输入(ReadStatus 和 SetStatus)和输出(CanExecutePSRead)。
-
记录 PSRead 的执行情况和 WaitForPowerStatus 的等待过程,便于调试。
-
-
代码简洁性:
-
合并状态管理到 UpdatePowerStatus,减少重复逻辑。
-
将 PSRead 封装为单独方法 ExecutePSRead,提高代码复用性。
-
WaitForPowerStatus 提供通用等待机制,适用于其他需要等待状态的场景。
-
使用示例
假设你有一个设置电压的场景,需要等待电源状态就绪:
csharp
// 主程序
public void Main()
{
// 启动 Read 线程(假设在后台运行)
Task.Run(() => Read());
// 设置电压
SetVoltage();
// 模拟设置状态变化
AUXInsMap["TestPowerSet"] = false; // 设置为 false
AUXSET(); // 更新状态
ExecutePSRead(); // 不会执行,因为 CanExecutePSRead = false
// 恢复设置状态
AUXInsMap["TestPowerSet"] = true;
AUXSET();
SetVoltage(); // 再次等待状态
}
日志输出示例:
Read: ReadStatus=true, SetStatus=true, CanExecutePSRead=true
ExecutePSRead: PSRead executed
AUXSET: ReadStatus=true, SetStatus=false, CanExecutePSRead=false
ExecutePSRead: PSRead skipped: CanExecutePSRead=false
AUXSET: ReadStatus=true, SetStatus=true, CanExecutePSRead=true
WaitForPowerStatus: CanExecutePSRead is true, exiting wait
SetVoltage: Power status is ready, setting voltage...
进一步优化建议
-
异步等待机制:
-
如果阻塞式等待(Thread.Sleep)影响性能,可将 WaitForPowerStatus 改为异步:
csharp
public async Task<bool> WaitForPowerStatusAsync(int timeoutMs = 5000, int pollIntervalMs = 100) { var startTime = DateTime.Now; while ((DateTime.Now - startTime).TotalMilliseconds < timeoutMs) { lock (_lock) { if (GlobalCache.CanExecutePSRead) { Console.WriteLine("WaitForPowerStatusAsync: CanExecutePSRead is true, exiting wait"); return true; } } Console.WriteLine("WaitForPowerStatusAsync: Waiting..."); await Task.Delay(pollIntervalMs); } Console.WriteLine($"WaitForPowerStatusAsync: Timeout after {timeoutMs}ms"); return false; } public async Task SetVoltageAsync() { if (await WaitForPowerStatusAsync(timeoutMs: 5000)) { Console.WriteLine("SetVoltageAsync: Power status is ready, setting voltage..."); // 例如:await CallVoltageSetFunctionAsync(); } else { Console.WriteLine("SetVoltageAsync: Failed to set voltage due to timeout or invalid power status"); } }
-
-
事件驱动替代轮询:
-
如果硬件支持状态变更通知,可用事件替换 Read 的轮询:
csharp
public void Initialize() { AUXRealTimeState1.TestPowerStatusChanged += (sender, newStatus) => { lock (_lock) { UpdatePowerStatus(); } }; }
-
-
超时和错误处理:
-
在 WaitForPowerStatus 中添加错误处理,例如记录硬件状态异常:
csharp
public bool WaitForPowerStatus(int timeoutMs = 5000, int pollIntervalMs = 100) { var startTime = DateTime.Now; while ((DateTime.Now - startTime).TotalMilliseconds < timeoutMs) { lock (_lock) { if (GlobalCache.CanExecutePSRead) { Console.WriteLine("WaitForPowerStatus: CanExecutePSRead is true, exiting wait"); return true; } if (!Convert.ToBoolean(AUXInsMap["TestPowerSet"])) { Console.WriteLine("WaitForPowerStatus: SetStatus is false, aborting wait"); return false; // 设置为 false 直接退出 } } Console.WriteLine("WaitForPowerStatus: Waiting..."); Thread.Sleep(pollIntervalMs); } Console.WriteLine($"WaitForPowerStatus: Timeout after {timeoutMs}ms"); return false; }
-
-
状态变化通知:
-
如果其他模块需要实时响应 CanExecutePSRead 变化,可使用事件或委托:
csharp
public delegate void PowerStatusChangedHandler(bool canExecute); public static event PowerStatusChangedHandler PowerStatusChanged; private void UpdatePowerStatus() { lock (_lock) { var readStatus = AUXRealTimeState1.TestPowerStatus; var setStatus = Convert.ToBoolean(AUXInsMap["TestPowerSet"]); var newStatus = readStatus && setStatus; if (newStatus != GlobalCache.CanExecutePSRead) { GlobalCache.CanExecutePSRead = newStatus; PowerStatusChanged?.Invoke(newStatus); } Console.WriteLine($"UpdatePowerStatus: ReadStatus={readStatus}, SetStatus={setStatus}, CanExecutePSRead={GlobalCache.CanExecutePSRead}"); } }
-
总结
优化后的代码通过引入 GlobalCache.CanExecutePSRead 统一管理状态,基于 AUXRealTimeState1.TestPowerStatus 和 AUXInsMap["TestPowerSet"] 的逻辑与,确保:
-
硬件读取状态为 true 且设置状态为 true 时,允许 PSRead。
-
设置状态为 false 时,立即禁止 PSRead。
-
提供 WaitForPowerStatus 方法,支持其他模块(如电压设置)等待状态就绪。
-
线程安全和日志记录确保可靠性和可调试性。
如果有具体场景(如电压设置的具体逻辑、硬件响应时间或多线程细节),请提供更多信息,我可以进一步定制优化方案!
更多推荐

所有评论(0)