在仪器控制或硬件通信场景中,底层驱动抛出的异常往往晦涩难懂,如果直接弹窗给用户,既暴露实现细节,也难以定位问题。本文通过两段式异常处理策略,演示如何把“底层原始错误”转化为“上层可操作建议”。
一、需求场景
场景 A:参数设置不当 → 设备返回“带宽超限”。
允许降级到 CW 模式继续工作,并给用户清晰提示。场景 B:初始化失败 → 设备返回“致命错误”。
必须立即重置会话,阻断后续流程,并记录日志。
二、两段式异常处理模型
底层(Driver)——抛异常
↓
中层(API)——捕获 → 分类 → 二次抛/降级
↓
上层(UI)——统一弹窗/日志
底层:只抛不处理,保持纯净。
中层:根据
ErrorCode
/Message
判断严重程度,决定“降级”或“重新抛”。上层:只做展示,不处理业务。
三、代码实战
1. 中层 API —— 降级处理(场景 A)
使用ex.Message只会把异常文本抛给用户,不会附带线程信息
public void SwitchToARB()
{
try
{
session.SetARB(); // 可能抛 “Bandwidth exceeded”
}
catch (Exception ex)
{
// 降级:带宽超限 → 回退到 CW
OpenCW(); // 打开连续波
throw new UserFriendlyException("带宽超限,已自动回退到 CW 模式", ex.Message);
}
}
UI 层捕获:
private void Button_ARB_Click(object sender, RoutedEventArgs e)
{
try
{
arbGenerator.SwitchToARB();
}
catch (UserFriendlyException uex)
{
MessageBox.Show(uex.Message);
}
}
2. 中层 API —— 致命错误重置(场景 B)
public void Generation()
{
try
{
session.Initiate(); // 可能抛 “Hardware fatal”
}
catch (Exception ex)
{
// 致命错误:立即清理资源,防止句柄泄露
Close();
throw new SessionFatalException("设备初始化失败,会话已重置", ex.Message);
}
}
UI 层捕获:
try
{
signalGen.Generation();
}
catch (SessionFatalException fex)
{
MessageBox.Show(fex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return;; // 退出
}
五、小结
层级 | 职责 | 关键动作 |
---|---|---|
Driver | 抛原始异常 | 不处理 |
API | 分类 + 决策 | 降级 or 重抛 |
UI | 展示 + 日志 | 不处理业务 |
两段式异常处理让“错误”从“灾难”变成“信息”,既保证程序健壮,又提升用户体验。下次遇到底层错误,先想想属于哪一级,再决定是“回退”还是“熔断”。