既然是秘籍,显然是写一些大家不常找到的,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为什么死锁程序的分析]的更多相关文章

  1. 在微软平台上运行 SAP 应用程序

     本博客介绍了在微软平台上运行 SAP 应用程序的相关信息,作者在基于微软平台使用 SAP 方面有着数十年经验. 发布关于 Azure 的 SAP 说明 几个月前,SAP 针对适用于 SAP 软件 ...

  2. [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler

    [原创]推荐一款强大的.NET程序内存分析工具.NET Memory Profiler 1 官方网站:http://memprofiler.com/2 下载地址:http://memprofiler. ...

  3. VS2010/MFC编程入门之四(MFC应用程序框架分析)

    VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html   上一讲鸡啄米讲的是VS2010应用 ...

  4. [转]DllMain中不当操作导致死锁问题的分析——DllMain中要谨慎写代码(完结篇)

    在CSDN中发现这篇文章,讲解的比较详细,所以在这里备份一个.原文链接:http://blog.csdn.net/breaksoftware/article/details/8167641 DllMa ...

  5. 服务器程序源代码分析之三:gunicorn

    服务器程序源代码分析之三:gunicorn 时间:2014-05-09 11:33:54 类别:网站架构 访问: 641 次 gunicorn是一个python web 服务部署工具,类似flup,完 ...

  6. 开源GUI-Microwindows之程序入口分析

    **************************************************************************************************** ...

  7. SQL Server 死锁概念和分析

    锁的概念 锁是什么 锁是数据库中在并发操作情形下保护资源的机制.通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性. 锁的概念可分为几部分 锁资源(锁住什么) 锁模式( ...

  8. 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    秦鼎涛  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验一 通过汇编一个简单的C程序,分析汇编代码 ...

  9. 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处   <Linux内核分析>MOOC课程http: ...

随机推荐

  1. ASP.NET HighStock

    参考博客HighCharts/Highstock使用小结,使用汉化及中文帮助文档 参考博客highcharts与highstock实例

  2. TXT导入出现乱码

    错误#1 11:15 2012-12-19客户提供一txt文本文件,要求导入到数据库,选用dts导入工具,选择数据源步骤如下列预览时出现乱码解答#1 双击打开原始文件中文显示正常,将其另存为选择编码为 ...

  3. iOS tableViewCell侧滑改变收藏状态

                 /** * 图片素材 链接: http://pan.baidu.com/s/1mhi1sfQ 密码: w2wq */ #import <UIKit/UIKit.h> ...

  4. ASP.NET MVC Template

    http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html http://st ...

  5. ios-XML文档解析之SAX解析

    首先SAX解析xml *xml文档的格式特点是节点,大体思路是把每个最小的子节点作为对象的属性,每个最小子节点的'父'节点作为对象,将节点转化为对象,输出. 每个节点都是成对存在的,有开始有结束.有始 ...

  6. XP下安装MAC OS虚拟系统

    参考baidu经验: http://jingyan.baidu.com/article/e5c39bf5876c8b39d760331a.html 工具: 1.虚拟机软件:vmware worksta ...

  7. urllib下载文件

    import urllib 1.用urlib.urlretrieve f = urllib.urlretrieve('http://www.baidu.com/img/bdlogo.gif','/tm ...

  8. expect实现交互式脚本

    #!/usr/bin/expect -f ##告诉解释器用expect来解释 set timeout 6 ##设置超时时间 ] ## 这个是传递给脚本的第一个参数,并把参数赋值给user ] ## 这 ...

  9. The Struts dispatcher cannot be found. This is usually caused by using Strut

    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the assoc ...

  10. Unable to instantiate Action...............

    当时找了好久都没搞明白,出现这样的问题,可能不是代码错了.将新添加的action不要添加在末尾,这样可能导致这样的问题出现,所以新添加的action最好放置在struts配置文件中间.