.net 串口通讯(蓝屏,死锁,卡死)
标签:?.net通讯textboxcomponentsbyteobject
2010-08-06 22:47?
1192人阅读?
?
收藏?
举报
版权声明:本文为博主原创文章,未经博主允许不得转载。
?? 到现在为止,用.net (vs2005)写串口通讯的程序写了好几回了,但到目前为止感觉才把问题解决得较好一些,网上也提供了不少方法,我大都用过,发现里面的问题还真不少。其实用过.net中serialPort类的设计人员都会遇到一些问题,但我想真正解决的人却不多。网上提供的方法至少我是没有找到一种行的.我还是先说说会遇到哪些问题吧。
?????? 我有一个朋友说写的串口程序会使系统蓝屏,我也试用,刚开始写的程序,的确会有大问题,蓝屏了。但引起蓝屏的应该不是程序,这里要究正一下。因为我们在测试的时候都是用虚拟串口的((SUDT SerialNull),我猜引起问题的是这个东西,因为我用单片机的时候是不会出现蓝屏,但发送和接收会出现问题。
????? 其次会出现的一个问题是当关闭串口的那个时值程序会卡死,只右击程序才能缓解过来。说来也怪,会出现卡也就算了,但它不是每回都出现,只是偶尔,真是麻烦死了。后来查阅了大量的资料,才发现其实程序中的线程造成死锁引起的,当关闭串口的那一刻,单片机又发送数据,引起一个事件而造成死锁。其实这不是我们的问题,是微软的问题,但愿以后的版本中它能改进,把问题解决。废话说了那么多,还是用代码说话更权威吧。
以下是我的程序源代码(里面和一些代码你会发现与网上流传的相同,那是因为那些都是大同小异,为了省事我就直接copy了部分。但那些流传的是有错误的,运行会出现大问题) 
?
?
定义了两个Button,它们的Name 分别是buttonOpenClose(打开关闭按键)和buttonSend(发送区中的发送按键)都有click事件
定义了两个TextBox,它们的Name 分别是txGet(接收区中的textBox,显示接收的数据)和txSend(发送区的textBox,用于发送数据)
定义了两个comboBox,它们的Name 分别是comboPortName(端口号那个)和comboBaudrate(波特率那个)
这里的核心代码其实也就那么几句:其中一个是通过委托,然后在接收数据的事件中调用this.Invoke();
??????????????????????????????????????????????? 另外一个就是设置两个变量,一个是Listening和Closing,防止死锁
?
?
?
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO.Ports; //using System.Linq;
using System.Text.RegularExpressions; namespace 解决串口关闭死锁 { ??? public partial class SerialportSampleForm : Form ??? { ??????? private SerialPort comm = new SerialPort();??? ??????? private StringBuilder builder = new StringBuilder(); ?????? //避免在事件处理方法中反复的创建,定义到外面。??? ??????? private long received_count = 0;//接收计数??? ??????? private long send_count = 0;//发送计数??? ??????? private bool Listening = false; ?????? //是否没有执行完invoke相关操作??? ??????? private bool Closing = false; ????? //是否正在关闭串口,执行Application.DoEvents, 并阻止再次invoke??? ????
??????? public SerialportSampleForm() ??????? { ??????????? InitializeComponent(); ??????? } ??????? public static byte[] HexStringToBinary(string hexstring)//十六进制格式转换 ??????? {
??????????? string[] tmpary = hexstring.Trim().Split(' '); ??????????? byte[] buff = new byte[tmpary.Length]; ??????????? for (int i = 0; i < buff.Length; i++) ??????????? { ??????????????? buff[i] = Convert.ToByte(tmpary[i],16);//转换 ??????????? } ??????????? return buff; ??????? } ??????? private void SerialportSampleForm_Load(object sender,EventArgs e) ??????? { ??????????? string[] ports = SerialPort.GetPortNames(); ??????????? Array.Sort(ports); ??????????? comboPortName.Items.AddRange(ports); ??????????? comboPortName.SelectedIndex = ??????????? comboPortName.Items.Count > 0 ? 0 : -1; ??????????? comboBaudrate.SelectedIndex = comboBaudrate.Items.IndexOf("9600");
??????????? ??????????? //初始化SerialPort对象 ??????????? comm.NewLine = "/r/n"; ??????????? comm.RtsEnable = true; ??????????? //根据实际情况吧。
??????????? //添加事件注册 ??????????? comm.DataReceived +=comm_DataReceived; ??????????? ??????? } ??????? void comm_DataReceived(object sender,SerialDataReceivedEventArgs e) ??????? ??????? { ?????????? ??????????? if (Closing) ??????????? {?? ??????????????? return;? ??????????? } ?????? //如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环??? ?????? ??????????? try?? ??????????? {??? ??????????????? Listening = true; ??????????? //设置标记,说明我已经开始处理数据,?? 一会儿要使用系统UI的。??? ????????????? ??????????????? int n = comm.BytesToRead; ??????????? //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致??? ???????????? ??????????????? byte[] buf = new byte[n]; ???????????? //声明一个临时数组存储当前来的串口数据??? ??????????????? received_count += n;//增加接收计数??? ??????????????? comm.Read(buf,n);//读取缓冲数据??? ???????????? //?? builder.Clear();//清除字符串构造器的内容? ??????? ????????????????//因为要访问ui资源,所以需要使用invoke方式同步ui。??? ????????????????this.Invoke((EventHandler)(delegate?? ??????????????? {??? ??????????????????? //判断是否是显示为16禁止??? ??????????????????? if (checkBoxHexView.Checked)??? ??????????????????? {??? ??????????????????????? //依次的拼接出16进制字符串??? ??????????????????????? foreach (byte b in buf)??? ??????????????????????? {??? ??????????????????????????? builder.Append(b.ToString("X2") + " ");??? ??????????????????????????? ??????????????????????? }??? ??????????????????? }??? ??????????????????? else?? ??????????????????? {??? ??????????????????????? //直接按ASCII规则转换成字符串??? ??????????????????????? builder.Append(Encoding.ASCII.GetString(buf));??? ??????????????????? }??? ?????????????? ??????????????????? this.txGet.Text=(builder.ToString());? ??????????????????? //修改接收计数??? ??????????????????? labelGetCount.Text = "Get:" + received_count.ToString();??? ??????????????? }));??? ??????????? }??? ??????????? finally?? ??????????? {??? ??????????????? Listening = false;//我用完了,ui可以关闭串口了。??? ??????????? }??? ??????? }
??????? private void buttonOpenClose_Click(object sender,EventArgs e) ??????? { ??????????? //根据当前串口对象,来判断操作??? ??????????? if (comm.IsOpen)??? ??????????? {??? ????????????????Closing = true;??? ??????????????? while (Listening) Application.DoEvents();??? ??????????????? //打开时点击,则关闭串口??? ??????????????? comm.Close(); ??????????????? MessageBox.Show(Listening.ToString()); ??????????? }??? ??????????? else?? ??????????? {
??????????????? Closing = false; ??????????????? //关闭时点击,则设置好端口,波特率后打开??? ??????????????? comm.PortName = comboPortName.Text;??? ??????????????? comm.BaudRate = int.Parse(comboBaudrate.Text);??? ??????????????? try?? ??????????????? {??? ??????????????????? comm.Open();??? ??????????????? }??? ??????????????? catch(Exception ex)??? ??????????????? {??? ??????????????????? //捕获到异常信息,创建一个新的comm对象,之前的不能用了。??? ??????????????????? ??????????????????? comm = new SerialPort();??? ??????????????????? //现实异常信息给客户。??? ??????????????????? MessageBox.Show(ex.Message);??? ??????????????? }??? ??????????? }??? ??????????? //设置按钮的状态??? ??????????? buttonOpenClose.Text = comm.IsOpen ? "Close" : "Open"; ??????????? buttonSend.Enabled = comm.IsOpen; ??????? }
??????? private void buttonSend_Click(object sender,EventArgs e) ??????? { ??????????? //定义一个变量,记录发送了几个字节??? ??????????? int n = 0;??? ??????????? //16进制发送??? ??????????? if (checkBoxHexSend.Checked)??? ??????????? {??? ???????????????
??????????????? byte[] send = HexStringToBinary(txSend.Text.Trim());
????????????? comm.Write(send,send.Length); ?????????? ???? ??????????????? //记录发送的字节数??? ????????????? n++; ??????????? }??? ??????????? else//ascii编码直接发送??? ??????????? {??? ?????????????? ??????????????????? comm.Write(txSend.Text);??? ??????????????????? n = txSend.Text.Length;??? ????????????????? ??????????? }??? ??????????? send_count += n;//累加发送字节数??? ??????????? labelSendCount.Text = "Send:" + send_count.ToString(); ?????????? //更新界面??
??????? }
????? ??? } }
?
?
以下是界面设计的代码:
?
?
namespace 解决串口关闭死锁 { ??? partial class SerialportSampleForm ??? { ??????? /// <summary> ??????? /// 必需的设计器变量。 ??????? /// </summary> ??????? private System.ComponentModel.IContainer components = null;
??????? /// <summary> ??????? /// 清理所有正在使用的资源。 ??????? /// </summary> ??????? /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> ??????? protected override void Dispose(bool disposing) ??????? { ??????????? if (disposing && (components != null)) ??????????? { ??????????????? components.Dispose(); ??????????? } ??????????? base.Dispose(disposing); ??????? }
??????? #region Windows 窗体设计器生成的代码
??????? /// <summary> ??????? /// 设计器支持所需的方法 - 不要 ??????? /// 使用代码编辑器修改此方法的内容。 ??????? /// </summary> ??????? private void InitializeComponent() ??????? { ??????????? this.comboPortName = new System.Windows.Forms.ComboBox(); ??????????? this.comboBaudrate = new System.Windows.Forms.ComboBox(); ??????????? this.checkBoxHexView = new System.Windows.Forms.CheckBox(); ??????????? this.labelGetCount = new System.Windows.Forms.Label(); ??????????? this.buttonOpenClose = new System.Windows.Forms.Button(); ??????????? this.buttonSend = new System.Windows.Forms.Button(); ??????????? this.labelSendCount = new System.Windows.Forms.Label(); ??????????? this.checkBoxHexSend = new System.Windows.Forms.CheckBox(); ??????????? this.txSend = new System.Windows.Forms.TextBox(); ??????????? this.txGet = new System.Windows.Forms.TextBox(); ??????????? this.label1 = new System.Windows.Forms.Label(); ??????????? this.label2 = new System.Windows.Forms.Label(); ??????????? this.label3 = new System.Windows.Forms.Label(); ??????????? this.label4 = new System.Windows.Forms.Label(); ??????????? this.groupBox1 = new System.Windows.Forms.GroupBox(); ??????????? this.groupBox2 = new System.Windows.Forms.GroupBox(); ??????????? this.groupBox3 = new System.Windows.Forms.GroupBox(); ??????????? this.groupBox4 = new System.Windows.Forms.GroupBox(); ??????????? this.groupBox1.SuspendLayout(); ??????????? this.groupBox2.SuspendLayout(); ??????????? this.groupBox3.SuspendLayout(); ??????????? this.groupBox4.SuspendLayout(); ??????????? this.SuspendLayout(); ??????????? //? ??????????? // comboPortName ??????????? //? ??????????? this.comboPortName.FormattingEnabled = true; ??????????? this.comboPortName.Location = new System.Drawing.Point(60,20); ??????????? this.comboPortName.Name = "comboPortName"; ??????????? this.comboPortName.Size = new System.Drawing.Size(121,20); ??????????? this.comboPortName.TabIndex = 0; ??????????? //? ??????????? // comboBaudrate ??????????? //? ??????????? this.comboBaudrate.FormattingEnabled = true; ??????????? this.comboBaudrate.Items.AddRange(new object[] { ??????????? "9600"}); ??????????? this.comboBaudrate.Location = new System.Drawing.Point(60,56); ??????????? this.comboBaudrate.Name = "comboBaudrate"; ??????????? this.comboBaudrate.Size = new System.Drawing.Size(121,20); ??????????? this.comboBaudrate.TabIndex = 1; ??????????? //? ??????????? // checkBoxHexView ??????????? //? ??????????? this.checkBoxHexView.AutoSize = true; ??????????? this.checkBoxHexView.Checked = true; ??????????? this.checkBoxHexView.CheckState = System.Windows.Forms.CheckState.Checked; ??????????? this.checkBoxHexView.Location = new System.Drawing.Point(80,29); ??????????? this.checkBoxHexView.Name = "checkBoxHexView"; ??????????? this.checkBoxHexView.Size = new System.Drawing.Size(96,16); ??????????? this.checkBoxHexView.TabIndex = 2; ??????????? this.checkBoxHexView.Text = "十六进制显示"; ??????????? this.checkBoxHexView.UseVisualStyleBackColor = true; ??????????? //? ??????????? // labelGetCount ??????????? //? ??????????? this.labelGetCount.AutoSize = true; ??????????? this.labelGetCount.Location = new System.Drawing.Point(33,31); ??????????? this.labelGetCount.Name = "labelGetCount"; ??????????? this.labelGetCount.Size = new System.Drawing.Size(29,12); ??????????? this.labelGetCount.TabIndex = 4; ??????????? this.labelGetCount.Text = "接收"; ??????????? //? ??????????? // buttonOpenClose ??????????? //? ??????????? this.buttonOpenClose.Location = new System.Drawing.Point(258,319); ??????????? this.buttonOpenClose.Name = "buttonOpenClose"; ??????????? this.buttonOpenClose.Size = new System.Drawing.Size(75,37); ??????????? this.buttonOpenClose.TabIndex = 5; ??????????? this.buttonOpenClose.Text = "打开"; ??????????? this.buttonOpenClose.UseVisualStyleBackColor = true; ??????????? this.buttonOpenClose.Click += new System.EventHandler(this.buttonOpenClose_Click); ??????????? //? ??????????? // buttonSend ??????????? //? ??????????? this.buttonSend.Location = new System.Drawing.Point(83,75); ??????????? this.buttonSend.Name = "buttonSend"; ??????????? this.buttonSend.Size = new System.Drawing.Size(75,23); ??????????? this.buttonSend.TabIndex = 6; ??????????? this.buttonSend.Text = "发送"; ??????????? this.buttonSend.UseVisualStyleBackColor = true; ??????????? this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click); ??????????? //? ??????????? // labelSendCount ??????????? //? ??????????? this.labelSendCount.AutoSize = true; ??????????? this.labelSendCount.Location = new System.Drawing.Point(33,64); ??????????? this.labelSendCount.Name = "labelSendCount"; ??????????? this.labelSendCount.Size = new System.Drawing.Size(29,12); ??????????? this.labelSendCount.TabIndex = 9; ??????????? this.labelSendCount.Text = "发送"; ??????????? //? ??????????? // checkBoxHexSend ??????????? //? ??????????? this.checkBoxHexSend.AutoSize = true; ??????????? this.checkBoxHexSend.Checked = true; ??????????? this.checkBoxHexSend.CheckState = System.Windows.Forms.CheckState.Checked; ??????????? this.checkBoxHexSend.Location = new System.Drawing.Point(82,22); ??????????? this.checkBoxHexSend.Name = "checkBoxHexSend"; ??????????? this.checkBoxHexSend.Size = new System.Drawing.Size(72,16); ??????????? this.checkBoxHexSend.TabIndex = 10; ??????????? this.checkBoxHexSend.Text = "十六进制"; ??????????? this.checkBoxHexSend.UseVisualStyleBackColor = true; ??????????? //? ??????????? // txSend ??????????? //? ??????????? this.txSend.Location = new System.Drawing.Point(82,46); ??????????? this.txSend.Name = "txSend"; ??????????? this.txSend.Size = new System.Drawing.Size(82,21); ??????????? this.txSend.TabIndex = 12; ??????????? //? ??????????? // txGet ??????????? //? ??????????? this.txGet.Location = new System.Drawing.Point(82,52); ??????????? this.txGet.Multiline = true; ??????????? this.txGet.Name = "txGet"; ??????????? this.txGet.Size = new System.Drawing.Size(112,21); ??????????? this.txGet.TabIndex = 13; ??????????? //? ??????????? // label1 ??????????? //? ??????????? this.label1.AutoSize = true; ??????????? this.label1.Location = new System.Drawing.Point(17,52); ??????????? this.label1.Name = "label1"; ??????????? this.label1.Size = new System.Drawing.Size(65,12); ??????????? this.label1.TabIndex = 14; ??????????? this.label1.Text = "发送数据:"; ??????????? //? ??????????? // label2 ??????????? //? ??????????? this.label2.AutoSize = true; ??????????? this.label2.Location = new System.Drawing.Point(24,58); ??????????? this.label2.Name = "label2"; ??????????? this.label2.Size = new System.Drawing.Size(65,12); ??????????? this.label2.TabIndex = 15; ??????????? this.label2.Text = "接收数据:"; ??????????? //? ??????????? // label3 ??????????? //? ??????????? this.label3.AutoSize = true; ??????????? this.label3.Location = new System.Drawing.Point(6,23); ??????????? this.label3.Name = "label3"; ??????????? this.label3.Size = new System.Drawing.Size(29,12); ??????????? this.label3.TabIndex = 16; ??????????? this.label3.Text = "端口"; ??????????? //? ??????????? // label4 ??????????? //? ??????????? this.label4.AutoSize = true; ??????????? this.label4.Location = new System.Drawing.Point(6,56); ??????????? this.label4.Name = "label4"; ??????????? this.label4.Size = new System.Drawing.Size(41,12); ??????????? this.label4.TabIndex = 17; ??????????? this.label4.Text = "波特率"; ??????????? //? ??????????? // groupBox1 ??????????? //? ??????????? this.groupBox1.Controls.Add(this.txSend); ??????????? this.groupBox1.Controls.Add(this.label1); ??????????? this.groupBox1.Controls.Add(this.buttonSend); ??????????? this.groupBox1.Controls.Add(this.checkBoxHexSend); ??????????? this.groupBox1.Location = new System.Drawing.Point(316,170); ??????????? this.groupBox1.Name = "groupBox1"; ??????????? this.groupBox1.Size = new System.Drawing.Size(223,114); ??????????? this.groupBox1.TabIndex = 20; ??????????? this.groupBox1.TabStop = false; ??????????? this.groupBox1.Text = "发送区"; ??????????? //? ??????????? // groupBox2 ??????????? //? ??????????? this.groupBox2.Controls.Add(this.txGet); ??????????? this.groupBox2.Controls.Add(this.label2); ??????????? this.groupBox2.Controls.Add(this.checkBoxHexView); ??????????? this.groupBox2.Location = new System.Drawing.Point(50,170); ??????????? this.groupBox2.Name = "groupBox2"; ??????????? this.groupBox2.Size = new System.Drawing.Size(223,114); ??????????? this.groupBox2.TabIndex = 21; ??????????? this.groupBox2.TabStop = false; ??????????? this.groupBox2.Text = "接收区"; ??????????? //? ??????????? // groupBox3 ??????????? //? ??????????? this.groupBox3.Controls.Add(this.labelGetCount); ??????????? this.groupBox3.Controls.Add(this.labelSendCount); ??????????? this.groupBox3.Location = new System.Drawing.Point(316,28); ??????????? this.groupBox3.Name = "groupBox3"; ??????????? this.groupBox3.Size = new System.Drawing.Size(200,99); ??????????? this.groupBox3.TabIndex = 22; ??????????? this.groupBox3.TabStop = false; ??????????? this.groupBox3.Text = "统计区"; ??????????? //? ??????????? // groupBox4 ??????????? //? ??????????? this.groupBox4.Controls.Add(this.comboPortName); ??????????? this.groupBox4.Controls.Add(this.comboBaudrate); ??????????? this.groupBox4.Controls.Add(this.label3); ??????????? this.groupBox4.Controls.Add(this.label4); ??????????? this.groupBox4.Location = new System.Drawing.Point(50,28); ??????????? this.groupBox4.Name = "groupBox4"; ??????????? this.groupBox4.Size = new System.Drawing.Size(200,99); ??????????? this.groupBox4.TabIndex = 23; ??????????? this.groupBox4.TabStop = false; ??????????? this.groupBox4.Text = "设置区"; ??????????? //? ??????????? // SerialportSampleForm ??????????? //? ??????????? this.AutoScaleDimensions = new System.Drawing.SizeF(6F,12F); ??????????? this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; ??????????? this.ClientSize = new System.Drawing.Size(571,453); ??????????? this.Controls.Add(this.groupBox4); ??????????? this.Controls.Add(this.groupBox3); ??????????? this.Controls.Add(this.groupBox2); ??????????? this.Controls.Add(this.groupBox1); ??????????? this.Controls.Add(this.buttonOpenClose); ??????????? this.Name = "SerialportSampleForm"; ??????????? this.Text = "Form1"; ??????????? this.Load += new System.EventHandler(this.SerialportSampleForm_Load); ??????????? this.groupBox1.ResumeLayout(false); ??????????? this.groupBox1.PerformLayout(); ??????????? this.groupBox2.ResumeLayout(false); ??????????? this.groupBox2.PerformLayout(); ??????????? this.groupBox3.ResumeLayout(false); ??????????? this.groupBox3.PerformLayout(); ??????????? this.groupBox4.ResumeLayout(false); ??????????? this.groupBox4.PerformLayout(); ??????????? this.ResumeLayout(false);
??????? }
??????? #endregion
??????? private System.Windows.Forms.ComboBox comboPortName; ??????? private System.Windows.Forms.ComboBox comboBaudrate; ??????? private System.Windows.Forms.CheckBox checkBoxHexView; ??????? private System.Windows.Forms.Label labelGetCount; ??????? private System.Windows.Forms.Button buttonOpenClose; ??????? private System.Windows.Forms.Button buttonSend; ??????? private System.Windows.Forms.Label labelSendCount; ??????? private System.Windows.Forms.CheckBox checkBoxHexSend; ??????? private System.Windows.Forms.TextBox txSend; ??????? private System.Windows.Forms.TextBox txGet; ??????? private System.Windows.Forms.Label label1; ??????? private System.Windows.Forms.Label label2; ??????? private System.Windows.Forms.Label label3; ??????? private System.Windows.Forms.Label label4; ??????? private System.Windows.Forms.GroupBox groupBox1; ??????? private System.Windows.Forms.GroupBox groupBox2; ??????? private System.Windows.Forms.GroupBox groupBox3; ??????? private System.Windows.Forms.GroupBox groupBox4; ??? } }
?
?
如果你们发现运行有错误,谢谢留言,会及时更改。谢谢,另外,源代码的工程文件我会上传到资源共享里~~~~~~ (编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|