[转]微软SerialPort秘籍[SerialPort为什么死锁程序的分析]
既然是秘籍,显然是写一些大家不常找到的,MSDN里遗漏提示大家注意的东西。
用过.net 2.0中,自带SerialPort的人,大多都遇到过。莫名其妙的执行Close的时候会死掉的问题。而Wince,mobile下,甚至Write,WriteLine的时候也会死锁。这和串口底层驱动有关。
1.Close的时候死机问题
我只是猜测,Close执行的操作是调用2个API:
SetCommMask(m_hComPort,0);
WaitForSingleObject(m_pThread->m_hThread,INFINITE);
m_pThread=NULL;
if(m_hComPort!=INVALID_HANDLE_VALUE) CloseHandle(m_hComPort);
这里的话,SetCommMask操作的时候。如果你的DeviceReceived事件没执行完,里面还有更新界面的操作。就会监听线程在等待,执行到界面操作,界面又要求关闭监听线程然后关闭串口。死锁了。
[解决办法]
一个正确不会死机的串口程序(主要是DataReceived事件里如果要调用ui来显示数据或分析结果的时候。ui的效率不确定,ui可能快。可能慢,可能用户某个操作阻塞中,会导致DataReceived事件执行很长时间,不论如何,这个时间我们无法预料)。
应该在关闭之前执行这句
while (Environment.TickCount - i < 2000 && _isReceiving) Application.DoEvents();
2.WriteLine,Write死锁
串口必然会读写超时,你无法预测你软件运行的硬件都足够快,串口驱动都效率很高。并且读写超时是正常现象。但是微软的SerialPort类默认的读写超时都是-1,无限等待,如果串口驱动有效率陷阱,超时了。Write和WriteLine就导致软件死锁无法继续使用了。
[解决办法]
设置读写超时为1000毫秒
3.不知道有人注意过没,WriteLine好像和Write效果一样?不是一个错误,而是微软一个很奇怪的设计,他允许设置换行符,默认是"",你需要自己设置NewLine属性为"/r/n"。否则Write和WriteLine是一样的。
--------------------------------------------------------------------------------
下面演示一个标准的,不会软件死锁的基于SerialPort的例子:
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Collections.Generic;
namespace SerialSample
{
public partial class FormSerialSample : Form
{
//Fields
SerialPort _comm = new SerialPort("COM1", 19200);
bool _isReceiving = false;
//wince下4096字节为一页,一次分配一页内存可能会快。但不知道托管内存是否也如此
List<byte> buf = new List<byte>(4096);
//Construct
public FormSerialSample()
{
InitializeComponent();
}
bool Open()
{
_comm.WriteTimeout = 1000;//写超时,如果底层串口驱动效率问题,能有效的避免死锁
_comm.ReadTimeout = 1000;//读超时,同上
_comm.NewLine = "/r/n";//新行的文本,用于WriteLine方法中由系统附加在text后
_comm.DataReceived += OnComm;//注册事件
_comm.Open();//打开串口
return _comm.IsOpen;//返回打开结果
}
void Close()
{
//这里需要允许OnComm方法执行完。如果不这么做。可能会
//先由某个地方执行到了Close,然后监听线程触发,调用了OnComm
//OnComm执行完缓存,执行this.Invoke。不知道Invoke原理。可能是
//消息机制?那么你如果正在这个函数里,不释放的时候,你就不会继续
//处理消息,所以我们要关闭之前,手工的调用消息处理函数
_comm.DataReceived -= OnComm;//反注册事件,避免下次再执行进来。
//最大延迟2秒,并检测到OnComm退出则退出,处理系统消息队列中的消息
int i = Environment.TickCount;
while (Environment.TickCount - i < 2000 && _isReceiving) Application.DoEvents();
_comm.Close();//现在没有死锁了,关闭串口
}
void OnComm(object sender, SerialDataReceivedEventArgs e)
{
_isReceiving = true;//开始读
//缓存你的数据,注意,最好在Invoke之外缓存数据,只有更新UI的才需要Invoke
int count = _comm.BytesToRead;
if (count < 1) return;
byte[] tmpBuf = new byte[count];
_comm.Read(tmpBuf, 0, count);
//连续3k数据没分析,应该没啥用了。
//避免数据太多分析时候时间长导致效率明显下降
if (buf.Count > 3000) buf.Clear();
buf.AddRange(tmpBuf);
//分析数据
//自己实现
//匿名委托,用于this.Invoke调用。
EventHandler delUpdate = delegate
{
//执行你的更新ui操作
};
this.Invoke(delUpdate);
_isReceiving = false;//结束读
}
}
}
串口是没啥技术含量。但是这个微软的SerialPort实在给不少人带来了麻烦,死机是绝大多数人遇到的,我以前是MSDN,微软的技术论坛,CSDN,GOOGLE,Baidu都搜索了。甚至发了邮件给微软的wince开发组,没有任何答案。不求您觉得我写的有什么价值,但希望对有同样困惑的朋友。能搜索到此文章时候,解决一个隐含的问题。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wuyazhe/archive/2009/01/17/3806248.aspx
[转]微软SerialPort秘籍[SerialPort为什么死锁程序的分析]的更多相关文章
- 在微软平台上运行 SAP 应用程序
本博客介绍了在微软平台上运行 SAP 应用程序的相关信息,作者在基于微软平台使用 SAP 方面有着数十年经验. 发布关于 Azure 的 SAP 说明 几个月前,SAP 针对适用于 SAP 软件 ...
- [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler
[原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler 1 官方网站:http://memprofiler.com/2 下载地址:http://memprofiler. ...
- VS2010/MFC编程入门之四(MFC应用程序框架分析)
VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html 上一讲鸡啄米讲的是VS2010应用 ...
- [转]DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)
在CSDN中发现这篇文章,讲解的比较详细,所以在这里备份一个.原文链接:http://blog.csdn.net/breaksoftware/article/details/8167641 DllMa ...
- 服务器程序源代码分析之三:gunicorn
服务器程序源代码分析之三:gunicorn 时间:2014-05-09 11:33:54 类别:网站架构 访问: 641 次 gunicorn是一个python web 服务部署工具,类似flup,完 ...
- 开源GUI-Microwindows之程序入口分析
**************************************************************************************************** ...
- SQL Server 死锁概念和分析
锁的概念 锁是什么 锁是数据库中在并发操作情形下保护资源的机制.通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性. 锁的概念可分为几部分 锁资源(锁住什么) 锁模式( ...
- 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
秦鼎涛 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...
- 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的
实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处 <Linux内核分析>MOOC课程http: ...
随机推荐
- Android 菜单(OptionMenu)
菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu). 一.概述 ...
- 智能硬件+App移动新生态【北京、广州、深圳】
智能硬件+App移动新生态[10.24北京站] 时间:2015年10月24日13:30-16:30 地点:Wepac空间(海淀区北四环西路68号左岸工社6层) 主办:APICloud.机智云.智石科技 ...
- ubantu install chrome
ubantu apt-get installt -y openssh-server sudo apt-get -f install libappindicator1 libindicator7dpkg ...
- 源码维护基本命令diff_patch
源码维护基本命令 diff------生成源代码补丁diff [命令行选项] 源文件 新文件-r 递归处理相应目录-N 包含新文件到patch-u 输出统一格式(unified format),这种格 ...
- javascript学习笔记之DOM与表单
DOM(文档对象模型),猫叔了一个层次化的节点树 一.DOM NODE相关公共属性与方法 DOM中所有节点都实现了NODE接口,该接口的公共属性和方法如下: 1.节点基本属性 1)NodeType 节 ...
- python password输入
1.linux下用getpass,没有星号提示,符合linux风格 from getpass import getpasspwd = getpass('Enter the password: ') 2 ...
- Oracle 监听器日志文件过大导致监听异常
Oracle 监听器日志文件过大导致监听异常 db版本:11.2.0.1 os版本:windows2008 现象: 应用异常,无法连接数据库.登陆数据库服务器,查看监听已经断掉.尝试重启监听,重启失败 ...
- json数据传输有感
必须把object对象o给JSON.stringify(o) json字符串化 传到后台 前台js的对象某属性如果是Array 那后台就是Long[] idsArray 这种bean的属性对应 然 ...
- C++之路进阶——bzoj2152(聪聪可可)
F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser hyxzc Logout 捐赠本站 Notice:由于本OJ建立在 ...
- Could not create the view: An unexpected exception was thrown.问题解决
Could not create the view: An unexpected exception was thrown.问题解决 今天打开Myeclipse10的时候,发现server窗口出现一堆 ...