[精选]23 单个串口设备数据的连续接收izi.pptx
《[精选]23 单个串口设备数据的连续接收izi.pptx》由会员分享,可在线阅读,更多相关《[精选]23 单个串口设备数据的连续接收izi.pptx(44页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、工控程序设计工控程序设计学习情景学习情景2 2 串口设备的数据采集串口设备的数据采集3工控程序设计学习情景2.3 单个串口设备数据的连续接收 2.3.1 学习要点 1.知识点:线程的概念,委托的概念和使用方法,线程的创建和启动,工作者线程和用户界面线程之间的数据传递,线程同步技 2.技能点:工作者线程的创建,串口数据接收和处理操作的封装2.3.2 任务描述 1.在前一个情景中完成了接收和处理单一串口设备数据的工作任务。实际应用中,上位机需要连续地接收和处理下位机发送的数据,而且在等待和接收数据的时候,用户界面不能停止响应。接收数据和响应用户输入这两个工作在宏观上是同时进行的,为了满足该需求,必
2、须采用多线程模式来进行程序设计。2.该教学情景通过“在工作者线程中接收HSDZC电能综合测试仪的”“HSDZC电能综合测试仪数据接收和处理操作的封装”这两个实施步骤达到连续接收接收单个串口设备(下位机)数据的目的。4工控程序设计学习情景2.3 单个串口设备数据的连续接收v2.3.3 相关知识v 1 多线程技术概述v(1)线程的概念v Windows是一个抢占式多任务操作系统,在系统内核中提供了对多线程的支持,多线程技术可以让应用程序在一个耗时的操作中能够及时对用户操作进行响应,并且从宏观上达到多个任务“齐头并进”的目的v 进程是应用程序的一个运行例程,是应用程序的一次动态执行过程。线程是被系统
3、独立调度和分派的基本单位,线程自己不拥有系统资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。每个进程至少需要一个执行线程,由系统自动创建,程序设计者可以根据需要创建其它线程。由于多个线程共享进程中的全局变量和系统资源,所以线程间的切换比较容易,通信也比较方便。5工控程序设计学习情景2.3 单个串口设备数据的连续接收v(2).NET Framework对多线程的支持v.NET平台库提供了Thread类对线程进行处理,该类包含在System.Threading命名空间中,程序中需要包含语句“using System.Threading;”。编程人员可以通过创建一个Thread类的实例
4、来创建一个线程,并通过Thread类提供的方法对线程进行管理。Thread类的常用属性和方法如下表:v 表2.3.1 Thread类的常用属性和方法6工控程序设计学习情景2.3 单个串口设备数据的连续接收v 2 委托的概念和使用方法v C#中的委托的作用相当于C/C+中的函数指针,函数指针是一个函数的入口地址。必修使用函数指针的场合是:程序员A编写了函数f,该函数中需要执行另外一个参数和返回值已经确定,但名字暂时不能确定函数,所以给函数设置一个函数指针类型的形式参数;当程序员B使用函数f时,定义函数g,并把g的入口地址作为实际参数传递给函数f,这样就可以在f中执行函数g了。v 线程的启动是使用
5、函数指针的一个典型例子,在启动线程之前,先要给操作系统指明线程启动后执行哪一函数中包含的代码,这时就要把函数的指针传递给创建线程的函数。v 回调(完成后通知)是使用函数指针的另外一个典型例子。如程序员A编写了负责接收网络数据的函数f1,程序员B编写了负责处理数据的函数f2,那么就可以把f2的函数指针作为参数传递给函数f1,当f1接收数据完毕后,自动调用f2。所以回调的特点是:站在程序员B的角度看,函数由自己编写,但是不由自己调用,且不知道什么时候被调用(因为网络速度有快有慢),函数编写者要做的就是把函数指针传递出去。7工控程序设计学习情景2.3 单个串口设备数据的连续接收v 定义委托的关键字是
6、delegate,它是从System.Delegate类派生出来的。例如:v delegate int SomeDelegate(int p1,string p2);v/int p1和string p2是被引用函数的参数类型和名称。其中参数类型和参数的个数必须和被引用函数的类型与个数一致。v 3 创建和启动线程v 一个线程必须和一个方法的入口(委托)关联起来,线程启动后,自动从该入口进入,执行函数体中包含的内容。C#应用程序启动时,自动创建主线程,并进入Main方法开始执行,其它线程需要在程序里自己定义和启动。由于委托可以代表一个方法的入口,8工控程序设计学习情景2.3 单个串口设备数据的连续
7、接收 所以创建线程实例时只需要在Thread类的构造方法里传入一个委托实例即可,这个委托名叫ThreadStart,已经在线程命名空间中定义作了定义:v public delegate void ThreadStart();v 所以创建线程方式如下:v ThreadStart functionEntrance=new ThreadStart(threadFunction);v Thread t=new Thread(functionEntrance);v 在委托ThreadStart的构造方法里面传入的是方法名,这个方法可以是静态方法,也可以是某个对象的方法。线程对象创建后,我们就可以调用其S
8、tart方法开始线程的执行了。9工控程序设计学习情景2.3 单个串口设备数据的连续接收 我们可以在主线程里建立线程,也可以在线程里再创建线程,线程启动后会自动执行委托实例代表的方法,线程执行完后会自动销毁并释放其占用的资源。在一个新线程中执行带参数的函数,操作步骤如下:定义线程函数:private void paramThreadFunction(object param)/函数体 用ParameterizedThreadStart委托封装线程函数:10工控程序设计学习情景2.3 单个串口设备数据的连续接收v ParameterizedThreadStart functionEntrance=
9、v new ParameterizedThreadStart(paramThreadFunction);v 创建线程对象v hread t=new Thread(functionEntrance);v 启动线程v t.Start(param);/param为传入的参数,可以是任意对象11工控程序设计学习情景2.3 单个串口设备数据的连续接收v4 线程同步技术v多线程应用程序中的的线程启动后,执行的先后顺序是无法预知的,通常情况下多个线程会交错执行。但是在多个线程访问共享数据的情况下,必须对数据的访问进行同步。好比有两路车,一路自东向西,一路自南向北运行,在一个十字路口交汇。在十字路口以外的区域
10、可以看着私有区域,而十字路口则是共有区域,需要红绿灯或交警来维护秩序,即确保在同一时刻只能有一路车进入,而另外一路车必须等待,这就是现实生活中的线程同步问题。12工控程序设计学习情景2.3 单个串口设备数据的连续接收v 下面的例子展示了一个读数据线程和一个写数据线程同时运行的情况:v private static int a=new int5;v static void Main(string args)v v Thread t1=new Thread(new ThreadStart(threadFun1);v Thread t2=new Thread(new ThreadStart(thre
11、adFun2);v t1.Start();v t2.Start();v v private static void threadFun1()/线程函数1v v while(true)13工控程序设计学习情景2.3 单个串口设备数据的连续接收v v for(int i=0;i a.Length;i+)/将数组元素全部输出v System.Console.Write(ai+);v System.Console.WriteLine();v v v private static void threadFun2()/线程函数2v v int flag=0,i;v while(true)v v for(i
12、=0;i a.Length;i+)/将数组元素全部改为0或1v ai=flag;v flag=flag=0?1:0;v v 14工控程序设计学习情景2.3 单个串口设备数据的连续接收v 下面采用Monitor类来进行线程同步,使数据读、写操作称为原子操作。即达到这样的目的:在线程2写数据时,线程1等待,在线程1读数据时,线程2等待,使每次输出的结果全部为0或全部为1。v 当调用Monitor类的Enter(Object obj)方法时,会获取对象obj的独占权,直到调用Exit(Object obj)方法时,才会释放对obj的独占权。注意调用Enter方法的次数要和,调用Exit方法的次数相等
13、。Monitor类还提供了TryEnter方法,该方法尝试获取obj对象的独占权,当获取独占权失败时,将返回false。实现代码如下:15工控程序设计学习情景2.3 单个串口设备数据的连续接收v private static int a=new int5;v private static object obj=new object();v static void Main(string args)v v Thread t1=new Thread(new ThreadStart(threadFun1);v Thread t2=new Thread(new ThreadStart(threadFu
14、n2);v t1.Start();v t2.Start();v v private static void threadFun1()v v while(true)v v Monitor.Enter(obj);/线程1进入临界区活动时,线程2等待v for(int i=0;i a.Length;i+)v System.Console.Write(ai+);v System.Console.WriteLine();16工控程序设计学习情景2.3 单个串口设备数据的连续接收v Monitor.Exit(obj);/线程1出临界区后,线程2才可以进入v v v private static void
15、threadFun2()v v int flag=0,i;v while(true)v v Monitor.Enter(obj);/线程2进入临界区活动时,线程1等待v for(i=0;i a.Length;i+)v ai=flag;v flag=flag=0?1:0;v Monitor.Exit(obj);/线程2出临界区后,线程1才可以进入v v 17工控程序设计学习情景2.3 单个串口设备数据的连续接收v 5 工作者线程向用户界面线程传递数据v 用户界面线程简称UI线程,其主要特点是能响应Windows消息,主要负责接收用户输入和向用户展示程序执行结果。为了及时响应用户的输入,UI线程中
16、不应执行费时的运算,更不能被阻塞。v 工作者线程一般用于在后台进行费时运算或和慢速设备打交道,这种线程不响应Windows消息。在通信程序中,数据的发送和接收耗费的时间不确定。为了在通信过程中能够响应用户输入,通常在建立一个或多个工作者线程,在后台完成通信任务。v 工作者线程向运行在UI线程中的用户控件传递数据时,不能直接对对控件的属性和方法进行调用,而要先定义一个委托,再用控件的Invoke方法,切换到UI线程去执行委托所指向的函数,来更新控件显示的内容。v 在下面的程序中,工作线程每循环完一次,就更新UI线程中的控件属性,向用户报告当前步骤。程序界面和后台代码如下:18工控程序设计学习情景
17、2.3 单个串口设备数据的连续接收图2.3.1 工作者线程向UI线程传递数据private void btnRun_Click(object sender,EventArgs e)ThreadStart funEntrance=new ThreadStart(threadFun);Thread t=new Thread(funEntrance);t.IsBackground=true;t.Start();19工控程序设计学习情景2.3 单个串口设备数据的连续接收v private delegate void crossThreadDelegate(int i);/定义委托v void show
18、Value(int i)v v lblReport.Text=执行到了第+i+步;v v private void threadFun()v v crossThreadDelegate cdt=new crossThreadDelegate(showValue);v for(int i=1;i=5;i+)v v/Invoke方法将当前线程切换到UI线程,再执行委托指向的函数v this.Invoke(cdt,i);/this指代当前窗口v Thread.Sleep(1000);/延时,便于看清中间执行过程v 20工控程序设计学习情景2.3 单个串口设备数据的连续接收v 下面的程序在工作者线程的
19、线程函数中直接使用lblReport.Text属性,而没有用Invoke方法:v private void threadFun()v v for(int i=1;i=5;i+)v v lblReport.Text=执行到了第+i+步;v Thread.Sleep(1000);v v v 在运行时会捕获到图2.4.2所示的异常:21工控程序设计学习情景2.3 单个串口设备数据的连续接收 图2.3.2 后台线程向UI线程传递数据22工控程序设计学习情景2.3 单个串口设备数据的连续接收v 使用委托和Invoke方法会使代码复杂度增加,在实际应用中,可以用匿名委托来简化代码:v private de
20、legate void crossThreadDelegate();v private void threadFun()v v for(int i=1;i=5;i+)v v crossThreadDelegate cdt=delegate/匿名委托(无函数名showValue)v v lblReport.Text=执行到了第+i+步;v;v this.Invoke(cdt);/指向委托指向的函数v Thread.Sleep(1000);v v 23工控程序设计学习情景2.3 单个串口设备数据的连续接收v 2.3.4 任务实施v 1 在工作者线程中接收HSDZC电能综合测试仪的数据v(1)设计界
21、面v 在转机性能测试中需要读取HSDZC电能综合测试仪采集到的3个数值:输入功率、输出功率和功率因数,以测试电机效率,此时测试仪的是选择测量方式1。程序设计时的界面如图2.3.3,用3个文本框分别显示输入功率、输出功率和功率因数,控件名称分别为txtSrgl、txtScgl和txtGlys。v 该界面是整个钻机性能测试系统主界面的一部份,为了便于观察和调试,在界面的右边以十六进制形式显示收到的数据帧,程序运行时的界面如图2.3.4所示。24工控程序设计学习情景2.3 单个串口设备数据的连续接收v 图2.3.3 电机效率测试程序设计时界面25工控程序设计学习情景2.3 单个串口设备数据的连续接收
22、v图2.3.4 电机效率测试程序运行时界面26工控程序设计学习情景2.3 单个串口设备数据的连续接收v private void btnStart_Click(object sender,EventArgs e)v/启动工作者线程v ThreadStart funEntrance=new ThreadStart(threadFun);v Thread t=new Thread(funEntrance);v t.IsBackground=true;v stop=false;v t.Start();v v(3)编写在工作者线程中执行的函数v 点击“开始读数”按钮后时,启动一个工作者线程,线程执行函
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 精选 精选23 单个串口设备数据的连续接收izi 23 单个 串口 设备 数据 连续 接收 izi
限制150内