软件与串口设备进行通信时,需要监测串口的状态,以便更新串口设备的连接状态。
遗产代码中采用后台线程定时轮训进行监测。为了能够及时轮训,使用较小的轮训间隔。
轮训有一个冲突:
轮训间隔小,造成资源浪费;轮训间隔大,轮训不及时。
为避免一个线程的资源浪费改成事件监测。
/// <summary> /// Monitor serialport changes /// 尹永贤 /// yinyongxian@qq.com /// 2019-1-28 15:35:06 /// </summary> public static class SerialPortService { static SerialPortService() { serialPortNames = GetSerialPortNames(); MonitorDeviceChanges(); } private static string[] serialPortNames; private static ManagementEventWatcher arrival; private static ManagementEventWatcher removal; public static IEnumerable<string> SerialPortNames { get { return serialPortNames; } } public static event EventHandler<SerialPortsChangedEventArgs> SerialPortsChanged; private static void RaiseSerialPortsChanged(EventType eventType) { var handler = SerialPortsChanged; if (handler != null) { var eventArgs = new SerialPortsChangedEventArgs(eventType, serialPortNames); handler(null, eventArgs); } } private static void MonitorDeviceChanges() { try { var deviceArrivalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); var deviceRemovalQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3"); arrival = new ManagementEventWatcher(deviceArrivalQuery); removal = new ManagementEventWatcher(deviceRemovalQuery); arrival.EventArrived += (sender, e) => OnPortsChanged(EventType.Insertion); removal.EventArrived += (sender, e) => OnPortsChanged(EventType.Removal); arrival.Start(); removal.Start(); } catch (Exception) { // ignored } } private static void OnPortsChanged(EventType eventType) { lock (serialPortNames) { var availableSerialPorts = GetSerialPortNames(); if (!serialPortNames.SequenceEqual(availableSerialPorts)) { serialPortNames = availableSerialPorts; RaiseSerialPortsChanged(eventType); } } } private static string[] GetSerialPortNames() { try { var currentPortNames = SerialPort.GetPortNames(); return currentPortNames; } catch (Exception) { return Enumerable.Empty<string>().ToArray(); } } } public enum EventType { Insertion, Removal } public class SerialPortsChangedEventArgs : EventArgs { private readonly EventType eventType; private readonly string[] serialPortNames; public SerialPortsChangedEventArgs(EventType eventType, params string[] serialPortNames) { this.eventType = eventType; this.serialPortNames = serialPortNames; } public IEnumerable<string> SerialPortNames { get { return serialPortNames; } } public EventType EventType { get { return eventType; } } }