目       录

第八章           总体控制器的设计... 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

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

  1. [连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言

                                  目       录 前言 前言 刚参加工作,使用过VB.VC开发软件,随着C#的崛起,听说是C++++,公司决定以后开发软件使用C#,凭借在 ...

  2. [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计

    目       录 第三章           设备驱动的设计... 2 3.1           初始化设备... 4 3.2           运行设备接口设计... 4 3.3        ...

  3. [连载]《C#通讯(串口和网络)框架的设计与实现》- 10.宿主程序详细设计

    目       录 第十章           宿主程序详细设计... 2 10.1        配置文件设计... 3 10.2        加载设备驱动... 4 10.3        加载 ...

  4. 《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  5. [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍

    [连载]<C#通讯(串口和网络)框架的设计与实现>- 0.前言 目       录 第一章           通讯框架介绍... 2 1.1           通讯的本质... 2 1 ...

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

    目       录 第六章           通讯控制器的设计... 2 6.1           控制器接口... 2 6.2           串口控制器... 3 6.3          ...

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

    目       录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章           框架总体的设计... 2 2.1           ...

  8. [连载]《C#通讯(串口和网络)框架的设计与实现》- 5.串口和网络统一IO设计

    目       录 第五章           串口和网络统一IO设计... 2 5.1           统一IO接口... 2 5.1.1    串口IO.. 4 5.1.2    网络IO.. ...

  9. [连载]《C#通讯(串口和网络)框架的设计与实现》-4.设备驱动管理器的设计

    目       录 第四章           设备驱动管理器的设计... 2 4.1           接口定义... 2 4.2           设备容器... 7 4.3          ...

随机推荐

  1. 【开发软件】 在Mac下配置php开发环境:Apache+php+MySql

    本文地址 原文地址   本文提纲: 1. 启动Apache 2. 运行PHP 3. 配置Mysql 4. 使用PHPMyAdmin 5. 附录   有问题请先 看最后的附录   摘要: 系统OS X ...

  2. 最新的 cocoaPods 安装方法

    经过努力终于发现了最新的 解决cocoaPods安装的办法: taobao Gems 源已停止维护,现由 ruby-china 提供镜像服务 第一步:安装rvm, 不管需不需要升级ruby,rvm可以 ...

  3. NYOJ 455

    1.应该交代清楚,参加宴会的人不知道一共有多少顶帽子.假如知道有n顶帽子的话,第一次开灯看见有n-1只,自然就知道自己是第n顶黑帽子,所以应该是这n个人在第一次关灯就打自己脸,不过这么一来就没意思了, ...

  4. Membership三步曲之进阶篇 - 深入剖析Provider Model

    Membership 三步曲之进阶篇 - 深入剖析Provider Model 本文的目标是让每一个人都知道Provider Model 是什么,并且能灵活的在自己的项目中使用它. Membershi ...

  5. 我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践

    写在前面 插一句:本人超爱落网-<平凡的世界>这一期,分享给大家. 阅读目录: 关于DDD 前期分析 框架搭建 代码实现 开源-发布 后记 第一次听你,清风吹送,田野短笛:第一次看你,半弯 ...

  6. ABP源码分析四十六:ABP ZERO中的Ldap模块

    通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供Defaut ...

  7. [译]ZOOKEEPER RECIPES-Barriers

    Barrier 在分布式系统中常使用Barrier来阻塞进程,当满足一定条件后再恢复进行后续操作.Barrier在Zookeeper中可以通过设计一个Barrier节点来实现.Barrier 节点存在 ...

  8. es6学习笔记

    class Point { constructor(x, y) { this.x = x; this.y = y; } static classMethod() { console.log('fath ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(28)-系统小结

    系列目录 我们从第一节搭建框架开始直到二十七节,权限管理已经告一段落,相信很多有跟上来的园友,已经搭配完成了,并能从模块创建授权分配和开发功能了 我没有发布所有源代码,但在14节发布了最后的一次源代码 ...

  10. ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

    在<管道是如何处理HTTP请求的?>中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.这样一 ...