[连载]《C#通讯(串口和网络)框架的设计与实现》- 8.总体控制器的设计

简介: 目       录 第八章           总体控制器的设计... 2 8.1           总控制器的职能... 2 8.2           组装和释放部件... 3 8.3           事件响应... 5 8.4           小结... 9   第八章     总体控制器的设计     有了IO部分、设备驱动部分、显示部分、数据导出部分和服务组件部分等,在这些已经存在的接口上构建一个集成各部分的总控制器,协调各部分有序工作、事件响应和控制数据流向。

目       录

第八章           总体控制器的设计... 2

8.1           总控制器的职能... 2

8.2           组装和释放部件... 3

8.3           事件响应... 5

8.4           小结... 9

 

第八章     总体控制器的设计

    有了IO部分、设备驱动部分、显示部分、数据导出部分和服务组件部分等,在这些已经存在的接口上构建一个集成各部分的总控制器,协调各部分有序工作、事件响应和控制数据流向。

    另外,这个总控制器还负责与宿主程序进行交互,可以这样理解:总控制器是宿主程序与IO部分、设备驱动部分、显示部分、数据导出部分和服务组件部分之间交互的载体,并且是唯一的。结构示意图如下:

 

8.1    总控制器的职能

   总控制器(IDeviceController)的职能包括:增加和删除设备驱动、增加导出数据实例、增加图形显示实例、增加服务组件实例、单击服务事件、释放控制器资源等等。接口定义如下图:

 

8.2    组装和释放部件

     DeviceController是总控制器的实例体类,继承自IDeviceController接口。通过构造函数来完成对总控制器的初始化,代码如下:

public DeviceController()
{
       _devList = DeviceManager.GetInstance();
       _ioController = IOControllerManager.GetInstance();
       _runContainer = RunContainerForm.GetRunContainer();
       _runContainer.MouseRightContextMenuHandler += RunContainer_MouseRightContextMenuHandler;
       _dataShowController = new GraphicsShowController();
       _exportController = new ExportDataController();
       _appServiceManager = new AppServiceManager();
}

   通过ReleaseDeviceController接口来完成对总控制器的资源释放,代码如下:

public void ReleaseDeviceController()
{
       _ioController.RemoveAllController();
       _runContainer.RemoveAllDevice();
       _runContainer.MouseRightContextMenuHandler -= RunContainer_MouseRightContextMenuHandler;
       _exportController.RemoveAll();
       _dataShowController.RemoveAll();
       _appServiceManager.RemoveAll();
       IEnumerator<IRunDevice> devList = _devList.GetEnumerator();
       while (devList.MoveNext())
       {
              devList.Current.ExitDevice();
       }
       _devList.RemoveAllDevice();
}

     软件退出时释放资源要比软件启动时加载资源要复杂的多,这块涉及到两方面问题:(1)释放资源顺序,如果资源提前释放,那么往往会造成后边代码在执行过程中出现无法引用对象资源的现象,造成意想不到的结果,所以一定要对实例的可用性进行判断。(2)事务性的线程无法正常退出,造成软件界面已经关闭,但是后台进程却一直存在。特别是对线程退出的处理,框架平台采用了统一的线程退出机制,代码如下:

public void StartThead()
{
       if (_RunThread == null || !_RunThread.IsAlive)
       {
              this._IsExit = false;
              this._RunThread = new Thread(new ThreadStart(RunThead));
              this._RunThread.IsBackground = true; //该线程为后台线程
              this._RunThread.Name = "RunThread";
              this._RunThread.Start();
       }
}

private void RunThead()
{
       while (!_IsExit)
       {
              if(_IsExit)         //如果标识为true,则退出循环,退出线程
              {
                     break;
              }
              //事务处理
       }
}

public void StopThead()
{
       if (this._RunThread != null && this._RunThread.IsAlive)
       {
              this._IsExit = true;       //标识当前线程为可退出线程。
              this._RunThread.Join(1000);//阻塞调用线程,直到某个线程终止或经过了指定时间为止
              try
              {
                     _RunThread.Abort();    //为了防止线程没有退出,进行强行终止,有可能造成文件损坏
              }
              catch
              {
              }
       }
}

8.3    事件响应

     增加和删除设备驱动都会对设备的事件进行绑定和解绑。代码如下:

dev.DeviceRuningLogHandler += new DeviceRuningLogHandler(DeviceRuningLogHandler);
dev.UpdateContainerHandler += new UpdateContainerHandler(UpdateContainerHandler);
dev.DeviceObjectChangedHandler += new DeviceObjectChangedHandler(DeviceObjectChangedHandler);
dev.ReceiveDataHandler += new ReceiveDataHandler(ReceiveDataHandler);
dev.SendDataHandler += new SendDataHandler(SendDataHandler);
dev.COMParameterExchangeHandler += new COMParameterExchangeHandler(COMParameterExchangeHandler);
dev.DeleteDeviceHandler += new DeleteDeviceHandler(DeleteDeviceHandler);

     具体含义请参见《第3章 设备驱动的设计》中的“3.12 事件响应设计”,COMParameterExchangeHandler改变串口参数事件响应代码如下:

private void COMParameterExchangeHandler(object source, COMParameterExchangeArgs e)
{
       if (e == null)
       {
              return;
       }
       IRunDevice dev = this._devList.GetDevice(e.DeviceID.ToString());
       if (dev != null)
       {
              if (dev.CommunicationType == CommunicationType.COM)
              {
                     if (e.OldCOM != e.NewCOM)
                     {
                            //--------------对旧串口进行处理----------------//
                            IRunDevice[] oldCOMDevList = this._devList.GetDevices(e.OldCOM.ToString(), CommunicationType.COM);
                            //---------------检测当前串口设备数------------//
                            int existCOMCount = 0;
                            for (int i = 0; i < oldCOMDevList.Length; i++)
                            {
                                   if (oldCOMDevList[i].GetHashCode() != dev.GetHashCode())
                                   {
                                          existCOMCount++;
                                   }
                            }
                            //------------------------------------------//
                            if (existCOMCount <= 0)//该串口没有可用的设备
                            {
                                   IIOController oldCOMController = IOControllerManager.GetInstance().GetController(SessionCom.FormatKey(e.OldCOM));
                                   if (oldCOMController != null)
                                   {
                                          _ioController.CloseController(oldCOMController.Key);
                                   }

                                   else
                                   {
                                          DeviceMonitorLog.WriteLog(e.DeviceName, "该设备的串口控制器为空");
                                   }
                            }
                            //--------------对新串口进行处理----------------//
                            bool newCOMControllerExist = IOControllerManager.GetInstance().ContainController(SessionCom.FormatKey(e.NewCOM));
                            if (!newCOMControllerExist)
                            {
                                   IIOController newCOMController = _ioController.BuildController(e.NewCOM.ToString(), e.NewBaud.ToString(), CommunicationType.COM);
                                   if (newCOMController != null)
                                   {
                                          newCOMController.StartService();
                                        _ioController.AddController(newCOMController.Key.ToString(), newCOMController);
                                   }
                                   else
                                   {
                                          DeviceMonitorLog.WriteLog(e.DeviceName, "创建该设备的串口控制器失败");
                                   }
                            }
                            DeviceMonitorLog.WriteLog(e.DeviceName, String.Format("串口从{0}改为{1}", e.OldCOM.ToString(), e.NewCOM.ToString()));

                     }
                     else
                     {
                            if (e.OldBaud != e.NewBaud)
                            {
                                   ISessionCom comIO = (ISessionCom)SessionComManager.GetInstance().GetIO(SessionCom.FormatKey(e.OldCOM));
                                   if (comIO != null)
                                   {
                                          bool success = comIO.IOSettings(e.NewBaud);
                                          if (success)
                                          {
                                                 DeviceMonitorLog.WriteLog(e.DeviceName, String.Format("串口{0}的波特率从{1}改为{2}成功", e.OldCOM.ToString(), e.OldBaud.ToString(), e.NewBaud.ToString()));
                                          }
                                          else
                                          {
                                                 DeviceMonitorLog.WriteLog(e.DeviceName, String.Format("串口 {0} 的波特率从 {1} 改为 {2} 失败", e.OldCOM.ToString(), e.OldBaud.ToString(), e.NewBaud.ToString()));
                                          }
                                   }
                            }
                     }
              }
              else
              {
                     DeviceMonitorLog.WriteLog(e.DeviceName, "不是串口类型的设备");
              }
       }
}

    同时,还包括GraphicsShowClosedHandler和MouseRightContextMenuHandler两个事件。当关闭显示视图的时候会触发GraphicsShowClosedHandler事件,把当前视图从管理器中移除,并释放资源;当右键单击显示视图会触发MouseRightContextMenuHandler事件,以调用相应设备的上下文菜单。

8.4    小结

    总体控制器不是必须的,宿主程序完全可以直接与IO部分、设备驱动部分、显示部分、数据导出部分和服务组件部分进行交互。但是,为了结构清晰、方便扩展,在中间加了一层进行总体协调。

 

作者:唯笑志在

Email:504547114@qq.com

QQ:504547114

.NET开发技术联盟:54256083

文档下载:http://pan.baidu.com/s/1pJ7lZWf

官方网址:http://www.bmpj.net

相关文章
|
29天前
|
监控 安全
从 Racket 语言出发,创新员工网络监控软件的框架
在数字化企业环境中,员工网络监控软件对于保障信息安全和提升效率至关重要。Racket 语言凭借其独特特性和强大功能,为开发创新的监控软件提供了新可能。通过捕获和分析网络数据包、记录员工网络活动日志,甚至构建复杂的监控框架,Racket 能够满足企业的定制化需求,为企业信息安全和管理提供强有力支持。未来,基于 Racket 的创新解决方案将不断涌现。
36 6
|
4天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
26 6
|
11天前
|
机器学习/深度学习 人工智能
类人神经网络再进一步!DeepMind最新50页论文提出AligNet框架:用层次化视觉概念对齐人类
【10月更文挑战第18天】这篇论文提出了一种名为AligNet的框架,旨在通过将人类知识注入神经网络来解决其与人类认知的不匹配问题。AligNet通过训练教师模型模仿人类判断,并将人类化的结构和知识转移至预训练的视觉模型中,从而提高模型在多种任务上的泛化能力和稳健性。实验结果表明,人类对齐的模型在相似性任务和出分布情况下表现更佳。
25 3
|
1月前
|
安全 网络安全 区块链
网络安全与信息安全:构建数字世界的防线在当今数字化时代,网络安全已成为维护个人隐私、企业机密和国家安全的重要屏障。随着网络攻击手段的不断升级,从社交工程到先进的持续性威胁(APT),我们必须采取更加严密的防护措施。本文将深入探讨网络安全漏洞的形成原因、加密技术的应用以及提高公众安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
在这个数字信息日益膨胀的时代,网络安全问题成为了每一个网民不可忽视的重大议题。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全漏洞如同隐藏在暗处的“黑洞”,时刻准备吞噬掉我们的信息安全。而加密技术作为守护网络安全的重要工具之一,其重要性不言而喻。同时,提高公众的安全意识,也是防范网络风险的关键所在。本文将从网络安全漏洞的定义及成因出发,解析当前主流的加密技术,并强调提升安全意识的必要性,为读者提供一份详尽的网络安全指南。
|
2月前
|
存储 SQL 安全
网络安全与信息安全:守护数字世界的坚盾在这个高度数字化的时代,网络安全和信息安全已经成为个人、企业乃至国家安全的重要组成部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
随着互联网技术的飞速发展,网络安全问题日益凸显。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全事件层出不穷。本文将从网络安全漏洞的定义与分类入手,探讨常见的网络攻击手段;随后深入解析加密技术的原理及其在保护信息安全中的作用;最后强调提升公众与企业的安全意识的重要性,并提出具体的建议。通过综合运用这些知识点,我们可以更好地构建起一道道坚固的防线,守护我们的数字世界。
|
5天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
21 4
|
5天前
|
网络协议 物联网 API
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第26天】Python 是一门功能强大且易于学习的编程语言,Twisted 框架以其事件驱动和异步IO处理能力,在网络编程领域独树一帜。本文深入探讨 Twisted 的异步IO机制,并通过实战示例展示其强大功能。示例包括创建简单HTTP服务器,展示如何高效处理大量并发连接。
20 1
|
22天前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
39 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
4天前
|
网络协议 调度 开发者
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第27天】本文介绍了Python网络编程中的Twisted框架,重点讲解了其异步IO处理机制。通过反应器模式,Twisted能够在单线程中高效处理多个网络连接。文章提供了两个实战示例:一个简单的Echo服务器和一个HTTP服务器,展示了Twisted的强大功能和灵活性。
13 0
完成切换网络+修改网络连接图标提示的代码框架
完成切换网络+修改网络连接图标提示的代码框架