以下是一个完整的 C# WPF 程序实现方案,用于监控硬件设备状态变化(基于设备 SDK API)。我们将分步骤实现,包含状态轮询、事件通知、UI 绑定和错误处理。
1. 项目结构设计
cs
HardwareMonitor/
├── Models/ # 数据模型
│ └── DeviceStatus.cs
├── Services/ # 硬件服务层
│ ├── IDeviceService.cs
│ └── DeviceService.cs
├── ViewModels/ # MVVM 视图模型
│ └── MainViewModel.cs
├── Views/ # 用户界面
│ └── MainWindow.xaml
└── App.xaml # 应用程序入口
2. 实现步骤
(1) 定义设备状态模型
cs
// Models/DeviceStatus.cs
public class DeviceStatus : INotifyPropertyChanged
{
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set { _isConnected = value; OnPropertyChanged(); }
}
private double _temperature;
public double Temperature
{
get => _temperature;
set { _temperature = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
(2) 封装设备 SDK API
cs
// Services/IDeviceService.cs
public interface IDeviceService
{
DeviceStatus CurrentStatus { get; }
event EventHandler<DeviceStatus> StatusChanged;
void StartMonitoring();
void StopMonitoring();
}
// Services/DeviceService.cs
public class DeviceService : IDeviceService, IDisposable
{
private readonly Timer _pollingTimer;
private readonly DeviceSDK _sdk; // 假设这是硬件SDK的类
public DeviceStatus CurrentStatus { get; } = new DeviceStatus();
public event EventHandler<DeviceStatus>? StatusChanged;
public DeviceService()
{
_sdk = new DeviceSDK(); // 初始化SDK
_pollingTimer = new Timer(UpdateStatus, null, Timeout.Infinite, 1000);
}
public void StartMonitoring() => _pollingTimer.Change(0, 1000); // 每秒轮询
public void StopMonitoring() => _pollingTimer.Change(Timeout.Infinite, Timeout.Infinite);
private void UpdateStatus(object? state)
{
try
{
// 调用SDK获取状态
CurrentStatus.IsConnected = _sdk.GetConnectionStatus();
CurrentStatus.Temperature = _sdk.ReadTemperature();
// 触发事件
StatusChanged?.Invoke(this, CurrentStatus);
}
catch (Exception ex)
{
Debug.WriteLine($"监控错误: {ex.Message}");
}
}
public void Dispose()
{
_pollingTimer.Dispose();
_sdk.Disconnect();
}
}
(3) 实现 ViewModel
cs
// ViewModels/MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
private readonly IDeviceService _deviceService;
private string _statusMessage = "等待连接...";
public DeviceStatus Status { get; }
public string StatusMessage
{
get => _statusMessage;
set { _statusMessage = value; OnPropertyChanged(); }
}
public ICommand StartMonitoringCommand { get; }
public ICommand StopMonitoringCommand { get; }
public MainViewModel(IDeviceService deviceService)
{
_deviceService = deviceService;
Status = _deviceService.CurrentStatus;
// 命令绑定
StartMonitoringCommand = new RelayCommand(() =>
{
_deviceService.StartMonitoring();
StatusMessage = "监控中...";
});
StopMonitoringCommand = new RelayCommand(() =>
{
_deviceService.StopMonitoring();
StatusMessage = "已停止";
});
// 订阅状态变化事件
_deviceService.StatusChanged += (s, e) =>
{
StatusMessage = e.IsConnected ? "设备在线" : "设备离线";
};
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
(4) 创建 WPF 界面
XML
<!-- Views/MainWindow.xaml -->
<Window x:Class="HardwareMonitor.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="硬件监控" Height="300" Width="400">
<Grid Margin="10">
<StackPanel>
<TextBlock Text="{Binding StatusMessage}" FontSize="16" Margin="0,10"/>
<Border Background="{Binding Status.IsConnected, Converter={StaticResource BoolToBrushConverter}}"
CornerRadius="5" Padding="10" Margin="0,10">
<TextBlock Text="{Binding Status.IsConnected, Converter={StaticResource BoolToStatusConverter}}"
HorizontalAlignment="Center"/>
</Border>
<TextBlock Text="{Binding Status.Temperature, StringFormat='温度: {0}°C'}"
Margin="0,10"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="开始监控" Command="{Binding StartMonitoringCommand}" Margin="5" Width="100"/>
<Button Content="停止监控" Command="{Binding StopMonitoringCommand}" Margin="5" Width="100"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
(5) 依赖注入配置
cs
// App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 配置DI容器
var services = new ServiceCollection();
services.AddSingleton<IDeviceService, DeviceService>();
services.AddTransient<MainViewModel>();
services.AddTransient<MainWindow>();
var provider = services.BuildServiceProvider();
// 启动主窗口
var mainWindow = provider.GetRequiredService<MainWindow>();
mainWindow.DataContext = provider.GetRequiredService<MainViewModel>();
mainWindow.Show();
}
}
3. 关键功能实现
(1) 状态轮询优化
cs
// 使用CancellationToken实现可控轮询
private async Task RunPollingAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
UpdateStatus(null);
await Task.Delay(1000, token); // 异步延迟
}
}
(2) SDK 异常处理
cs
private void UpdateStatus(object? state)
{
try
{
// 添加超时控制
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
var status = Task.Run(() => _sdk.GetStatus(), cts.Token).Result;
// 更新状态...
}
catch (OperationCanceledException)
{
StatusMessage = "SDK响应超时";
}
catch (Exception ex)
{
Debug.WriteLine($"SDK错误: {ex.Message}");
}
}
(3) UI 绑定转换器
cs
// BoolToBrushConverter.cs
public class BoolToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Brushes.LightGreen : Brushes.LightPink;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
4. 部署与测试
硬件 SDK 集成
-
将厂商提供的 SDK DLL 放入
lib/
目录 -
在项目中添加引用:
XML
<ItemGroup>
<Reference Include="DeviceSDK" HintPath="lib\DeviceSDK.dll" />
</ItemGroup>
测试方案
测试类型 | 方法 | 预期结果 |
---|---|---|
正常连接测试 | 模拟SDK返回有效数据 | UI实时更新状态 |
断开连接测试 | 关闭硬件设备 | 显示"设备离线" |
压力测试 | 高频调用SDK API | 不出现UI卡顿或内存泄漏 |
异常测试 | 抛出SDK异常 | 显示错误且不崩溃 |
5. 扩展功能建议
- 历史数据记录
cs
public void LogStatus(DeviceStatus status)
{
File.AppendAllText("log.txt",
$"{DateTime.Now}: {status.Temperature}°C, Connected={status.IsConnected}\n");
}
- 阈值报警
cs
if (CurrentStatus.Temperature > 80)
{
PlayAlertSound();
ShowToast("温度过高!");
}
- 远程监控
cs
// 使用SignalR将状态推送到Web端
await _hubConnection.SendAsync("ReportStatus", CurrentStatus);
系统优点:
-
分层清晰(MVVM + 服务隔离)
-
响应灵敏(异步轮询 + 事件驱动)
-
健壮可靠(完备的错误处理)
-
易于扩展(依赖注入支持)
的硬件监控系统。实际开发时,请根据具体 SDK API 调整 DeviceService
中的调用逻辑。