C# 使用MVP在线程上运行的串行端口
我有一个名为C# 使用MVP在线程上运行的串行端口,c#,multithreading,user-interface,serial-port,mvp,C#,Multithreading,User Interface,Serial Port,Mvp,我有一个名为SerialClient的类,它通过串行端口发送/接收字节。调用SerialClient.Start()时,它进入无限while循环,直到调用SerialClient.Stop()。该类有一些属性,为了简单起见,比如说SerialClient.PropA,SerialClient.PropB 我需要在GUI中使用它。在GUI上,您可以调用Start、Stop并在属性更改时读取它们 为了在GUI中使用它,显然SerialClient需要在线程中操作,因为它是一个无止境的循环。因此,我用
SerialClient
的类,它通过串行端口发送/接收字节。调用SerialClient.Start()
时,它进入无限while循环,直到调用SerialClient.Stop()
。该类有一些属性,为了简单起见,比如说SerialClient.PropA
,SerialClient.PropB
我需要在GUI中使用它。在GUI上,您可以调用Start、Stop并在属性更改时读取它们
为了在GUI中使用它,显然SerialClient
需要在线程中操作,因为它是一个无止境的循环。因此,我用属性设置了视图,以匹配SerialClient
的属性。视图在演示者上调用Start()
和Stop()
在presenter中,我创建了一个新线程,并对SerialClient
的对象调用start。问题是当_serialClient抛出异常时,演示者无法捕获它,而且如果(serialClient.PropB
)等属性发生更改并调用其更改的事件处理程序,则需要在GUI线程上调用它们。我尝试使用后台工作程序,但无法使其工作(更改属性仍然会从非UI线程影响UI)
一定有一个简单的解决办法,我正在寻找。GUI只需要调用方法和读取属性,并防止异常使整个应用程序崩溃
有什么想法吗?您遇到了在C#中处理多线程应用程序时常见的两个问题:
?您是否正在处理.Net SerialPort类上的ErrorReceived和DataReceived?如果是,则在SerialClient类中没有。有一个OpenCOM()方法。这将在COM5上创建一个设置正确的串行端口(_comport),然后将其打开。所有这些都在Start()中,调用OpenCOM(),然后在SendReceivedData方法上创建一个新线程,该方法包含无止境循环。在这里,我循环读取_comport.BytesToRead,如果有数据,则循环读取_comport.Read(/*Read-In-data here*/),如果有数据要发送,则循环写入(/*my-data here*/)。是的,要读取字节,请不要使用循环,只要尝试使用DataReceived事件和ErrorReceived,如果可以,然后,当serialport调用DataReceived时,您可以读取所有数据并调用委托。谢谢!我会试试看。但我有两个问题。1) 谁应该启动线程?它应该在演示者中完成,还是应该由SerialClient.Start()负责创建线程。2) 如果com端口中发生错误,即断电中断连接,COM5不存在,这些抛出异常而不是ErrorReceived事件。这些将不会被UI线程捕获并使应用程序崩溃。我需要向UI引发异常以通知用户。例如,“您选择的COM端口正被另一个应用程序使用”。我认为我需要使用ISynchronizeInvoke来处理此问题,但它在Compact Framework中不可用。代码库必须独立于GUI,因此我无法通过包含控件来破解解决方案。唯一的方法是在使用Compact Framework时为所有内容编写调用处理程序,我已经做了这个更改。我有start方法,它包含启动线程的代码,这样其他人的APi就更容易了。然后我有一个叫做Exception的事件。当引发将转义线程化方法的异常时,将调用此函数。通过这种方式捕获并停止异常,线程停止并引发事件。我认为这是最好的解决办法,但我真的认为有更好的方法。我已经研究过如何调用GUI线程,但是所需的接口不在紧凑的框架中。
Thread thread = new Thread(_serialClient.Start);
thread.IsBackground = true;
thread.Start();
void someEvent_Handler(object sender, SomeEventEventArgs e)
{
if (this.Dispatcher.CheckAccess())
{
// do work on UI thread
}
else
{
// or BeginInvoke()
this.Dispatcher.Invoke(new Action(someEvent_Handler),
sender, e);
}
}