新的COM端口可用事件

时间:2012-05-11 11:39:48

标签: c# visual-studio events serial-port port

我的C#应用​​程序使用COM端口。我遇到了一些应该在大多数程序中都很常见的困难。当端口名称列表发生变化时,我需要获取一个事件。我有一个选择框,用户可以从中选择可用的端口名称列表。有没有人为此提供一段代码?谢谢。

3 个答案:

答案 0 :(得分:4)

也可以在“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;
}

}

答案 1 :(得分:3)

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

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);
}

答案 2 :(得分:2)

COM端口更改是一种罕见的事件,而不是常见事件。

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

更好的是,提供一个“刷新列表”按钮 - 如果用户已插入USB串行适配器,该列表基本上只会更改。