我正在用C#开发一个WPF应用程序,并正在与一个串行设备进行通信。目前在我的应用程序的主窗口中,我通过定期从串行设备读取行来显示我获得的一些信息。
有时我需要不断地从串行设备接收数据并将数据保存到文件中。我停止使用串口的其他方法(比如定期读取主窗口上显示的线路),这样就不会干扰录制过程。管理跨应用程序的串口访问可能很麻烦,因此" System.UnauthorizedAccessException"并不少见。
在使用串行设备的应用程序中的每个方法或窗口中,我定义一个新的串行端口,打开它,读取行,然后关闭并处理它。我已经读过,在应用程序启动时打开串口并在应用程序关闭时关闭它是一个好习惯,我可以看到为什么这对我使用此应用程序的位置有所帮助。我有一些问题:
答案 0 :(得分:0)
您应该创建一个单独的类来管理SerialPort连接。它应该有自己的线程从串口读取。然后,它可以将读取的信息分发到应用程序中的其他位置。一个好方法是使用Rx
。从这个类中创建一个单例并将其注入需要它的应用程序中的任何其他位置。
使用Rx
,您可以根据需要多次订阅来自串口的消息。
创建一个类来管理串口:
public class SerialPortManager
{
private SerialPort;
private string comPort;
Subject<string> messageBus = new Subject<string>();
public IObservable<string> MessageBus => messageBus;
private CancellationTokenSource cts = new CancellationTokenSource();
public SerialPortManager(string comPort)
{
this.comport = comport;
}
public void Start()
{
ThreadStart ts = new ThreadStart(SerialDeviceThread);
Thread t = new Thread(ts);
t.IsBackground = true;
t.Name = this.Name;
t.Start();
}
private void SerialDeviceThread()
{
this.serialPort = new SerialPort(this.comPort, ...);
while (true)
{
string line = this.serialPort.ReadLine();
this.messageBus.OnNext(line);
}
}
}
在某处创建此类的singelton:
public static Lazy<SerialPortManager> SerialPortManager =
new Lazy<SerialPortManager>(x => {
var sm = new SerialPortManager("COM2");
sm.Start();
return sm;
});
和其他地方
SerialPortManager.Value.MessageBus.Subscribe( ...)
[这仍然大大简化了,我会在串口上有逻辑来捕获故障并在断开连接时重新创建端口。我还使用依赖注入容器(例如Autofac)而不是静态值。]
答案 1 :(得分:0)
听起来你需要的是一个管理串口访问的对象。此对象将设置一次端口对象并启动一个新线程,该线程将从串行端口连续读取行,并在读取该行时触发事件。然后,当您希望收到来自串行端口的数据通知时,您的其他应用程序对象会将委托附加到该事件。这样,来自串口的数据将始终广播给感兴趣的人。根据您的UI,您必须在Dispatcher(对于WPF)或Windows表单对象(对于Windows表单)上使用Invoke()方法,以确保从UI线程触发事件,以便它可以正确调用UI方法