新的 COM 端口可用事件

本文关键字:事件 COM 新的 | 更新日期: 2023-09-27 18:34:03

我的C#应用程序使用COM端口。 我遇到了一些困难,这应该是大多数程序常见的。 当端口名称列表更改时,我需要获取一个事件。 我有一个选择框,用户可以在其中从可用端口名称列表中进行选择。 有人有一段代码吗? 谢谢。

新的 COM 端口可用事件

它也可以在"ManagementEventWatcher"的帮助下完成:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Management;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
namespace HmxFlashLoader
{
    /// <summary>
    /// Make sure you create this watcher in the UI thread if you are using the com port list in the UI
    /// </summary>
    [Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public sealed class SerialPortWatcher : IDisposable
    {
        public SerialPortWatcher()
        {
            _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            ComPorts = new ObservableCollection<string>(SerialPort.GetPortNames().OrderBy(s => s));
            WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent");
            _watcher = new ManagementEventWatcher(query);           
            _watcher.EventArrived += (sender, eventArgs) => CheckForNewPorts(eventArgs);
            _watcher.Start();       
        }
        private void CheckForNewPorts(EventArrivedEventArgs args)
        {
            // do it async so it is performed in the UI thread if this class has been created in the UI thread
            Task.Factory.StartNew(CheckForNewPortsAsync, CancellationToken.None, TaskCreationOptions.None, _taskScheduler);
        }
        private void CheckForNewPortsAsync()
        {
            IEnumerable<string> ports = SerialPort.GetPortNames().OrderBy(s => s);
            foreach (string comPort in ComPorts)
            {
                if (!ports.Contains(comPort))
                {
                    ComPorts.Remove(comPort);
                }
            }
            foreach (var port in ports)
            {           
                if (!ComPorts.Contains(port))
                {
                    AddPort(port);
                }
            }
        }
        private void AddPort(string port)
        {
            for (int j = 0; j < ComPorts.Count; j++)
            {
                if (port.CompareTo(ComPorts[j]) < 0)
                {
                    ComPorts.Insert(j, port);
                    break;
                }
            }
        }
        public ObservableCollection<string> ComPorts { get; private set; }
        #region IDisposable Members
        public void Dispose()
        {
            _watcher.Stop();    
        }
        #endregion
        private ManagementEventWatcher _watcher;
        private TaskScheduler _taskScheduler;
    }
}

COM端口更改是罕见的事件,并不常见。

最简单的方法是有一个计时器,每 10-30 秒枚举一次 COM 端口列表,如果更改,则更新列表。

更好的是,提供一个"刷新列表"按钮 - 列表基本上只有在用户插入USB串行适配器时才会更改。

创建一个简单的表单应用程序,并将以下代码放入表单中:

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case 537: //WM_DEVICECHANGE
            var ports = SerialPort.GetPortNames().OrderBy(name => name);
            foreach (var portName in ports)
            {
                Debug.Print(portName);
            }
            break;
    }
    base.WndProc(ref m);
}