串口;线程;委托;事件
Posted Ecr_hool
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了串口;线程;委托;事件相关的知识,希望对你有一定的参考价值。
1、构建方法时候,需要用界面来显示串口接收到的数据,所以我才用了,较为复杂的委托事件线程的方法,把串口接收的模块并入到我的主工程中;
总结一下串口模块的设计,
新建一个委托
public delegate void SerialPortEventHandler(Object sender, SerialPortEventArgs e);
新建一个事件 SerialPortEventArgs类,继承自事件数据的类的基类
public class SerialPortEventArgs : EventArgs
{
public bool isOpend = false;
public Byte[] receivedBytes = null;
}
新建一个ComModel类
在类中申明事件
public event SerialPortEventHandler comReceiveDataEvent = null;
public event SerialPortEventHandler comOpenEvent = null;
public event SerialPortEventHandler comCloseEvent = null;
private SerialPort sp = new SerialPort();
private Object thisLock = new Object();
在串口控件的事件中,有3个事件
当串口接收到数据时,触发 DataReceived 事件, 单击产生的方法中加入代码功能:
1.假如 sp.BytesToRead <= 0 ,返回。
2.锁住线程 lock (thisLock)
3.读取数据:
1 int len = sp.BytesToRead; 2 Byte[] data = new Byte[len]; 3 try 4 { 5 sp.Read(data, 0, len); 6 }
4.new出来自己定义的事件 SerialPortEventArgs
SerialPortEventArgs args = new SerialPortEventArgs();
事件中传送的数据
args.receivedBytes = data;
5.如果 事件comReceiveDataEvent ,不为空,则用事件......()
if (comReceiveDataEvent != null)
{
comReceiveDataEvent.Invoke(this, args);
}
//用事件通知界面
新建一个IController的类
Controller类是Form类和Model类的桥梁,在该Controller中,将界面上的更新函数注册到Model中。
public class IController { ComModel comModel = new ComModel(); IView view; public IController(IView view) { this.view = view; view.SetController(this); //将页面上的更新界面函数注册到Model的事件 comModel.comCloseEvent += new SerialPortEventHandler(view.CloseComEvent); comModel.comOpenEvent += new SerialPortEventHandler(view.OpenComEvent); comModel.comReceiveDataEvent += new SerialPortEventHandler(view.ComReceiveDataEvent); } }
一般来说Controller比较复杂的一部分,但在这个程序中比较简单,没有数据库相关的操作。
在界面层
声明一个接口 IView,并在mainform中引用这个接口 “public partial class FormMain : Form,IView”
public interface IView
{
void ComReceiveDataEvent(Object sender, SerialPortEventArgs e);
}
编写串口接收事件函数
public void ComReceiveDataEvent(object sender, SerialPortEventArgs e)
{
// // 摘要: // 获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。 // // 返回结果: // 如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 // true;否则为 false。 if (this.InvokeRequired) { try { // // 摘要: // 在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。 // // 参数: // method: // 一个方法委托,它采用的参数的数量和类型与 args 参数中所包含的相同。 // // args: // 作为指定方法的参数传递的对象数组。如果此方法没有参数,该参数可以是 null。 // // 返回结果: // System.Object,它包含正被调用的委托返回值;如果该委托没有返回值,则为 null。 Invoke(new Action<Object, SerialPortEventArgs>(ComReceiveDataEvent), sender, e); } catch (System.Exception) { //disable form destroy exception } return; } if (true) //字符串display as string { receivetbx.AppendText(Encoding.Default.GetString(e.receivedBytes)); receiveBytesCount += e.receivedBytes.Length; acceptStatusLabel.Text = "Received: " + receiveBytesCount.ToString(); }
}
以上是关于串口;线程;委托;事件的主要内容,如果未能解决你的问题,请参考以下文章
对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段