加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

.net 串口通讯(蓝屏,死锁,卡死)

发布时间:2021-05-20 14:34:56 所属栏目:大数据 来源: https://blog.csdn.net/kasama1
导读:.net 串口通讯(蓝屏,死锁,卡死) 标签:?.net通讯textboxcomponentsbyteobject 2010-08-06 22:47 ? 1192人阅读 ? 评论(0) ? 收藏 ? 举报 版权声明:本文为博主原创文章,未经博主允许不得转载。 ?? 到现在为止,用.net (vs2005)写串口通讯的程序写了好几

.net 串口通讯(蓝屏,死锁,卡死)

标签:?.net通讯textboxcomponentsbyteobject ? 1192人阅读? 评论(0)? 收藏? 举报

?? 到现在为止,用.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;
??? }
}

?

?

如果你们发现运行有错误,谢谢留言,会及时更改。谢谢,另外,源代码的工程文件我会上传到资源共享里~~~~~~

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读