国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[轉]微軟SerialPort秘籍[SerialPort為什么死鎖程序的分析]

2019-11-17 03:16:43
字體:
來源:轉載
供稿:網友

[轉]微軟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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 贵溪市| 瓦房店市| 吉安市| 宽城| 永昌县| 湟中县| 泸定县| 靖西县| 靖州| 庆城县| 盐池县| 叶城县| 徐闻县| 青龙| 灵山县| 武宁县| 扶沟县| 汉寿县| 江孜县| 平江县| 稷山县| 射阳县| 丰都县| 抚顺县| 诏安县| 赫章县| 白河县| 四会市| 保靖县| 沭阳县| 山阴县| 凌源市| 二连浩特市| 东安县| 栾城县| 南城县| 东莞市| 万宁市| 富宁县| 广州市| 娄烦县|