我需要一些背景工作者的帮助。我试图从串口读取数据(使用按钮正常工作)问题是我需要从串口连续读取,直到有人按下窗体上的按钮(关闭按钮)停止读取。我尝试通过添加一个循环来做到这一点,但它只是无限地运行并冻结了表单。我有以下代码,每当我按下按钮读取,就会创建一个文件,但是当我按下关闭端口按钮时,它会显示
I / O操作因线程退出或中断而中止 申请请求
有关如何解决此问题的任何想法?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
namespace SerialCommunication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
GetAvaliablePortNames();
}
bool indicator;
StreamWriter sw = new StreamWriter(@"C:\Users\slahiri\Desktop\Data\jumbo.txt");
void GetAvaliablePortNames()
{
string[] Ports = SerialPort.GetPortNames();
cmbPort.Items.AddRange(Ports);
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
if (cmbPort.Text == "" || cmbBaud.Text == "")
{
MessageBox.Show("Please select the Port and Baud Rates");
}
else
{
serialPort1.PortName = cmbPort.Text;
serialPort1.BaudRate = Convert.ToInt32(cmbBaud.Text);
serialPort1.Open();
progressBar1.Value = 100;
groupBox2.Enabled = true;
btnRead.Enabled = true;
btnOpen.Enabled = false;
btnClose.Enabled = true;
}
}
catch (UnauthorizedAccessException)
{
txtRead.Text = "Unauthorized Acess";
}
}
private void btnClose_Click(object sender, EventArgs e)
{
serialPort1.Close();
progressBar1.Value = 0;
btnClose.Enabled = false;
btnRead.Enabled = false;
btnOpen.Enabled = true;
indicator = true;
}
private void btnRead_Click(object sender, EventArgs e)
{
if (btnRead.Text == "Read")
{
btnRead.Text = "Stop and Close Port";
progressBar1.Maximum = 1000;
progressBar1.Value = 0;
backgroundWorker1.RunWorkerAsync(progressBar1.Maximum);
indicator = false;
}
else
{
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.CancelAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
int max = (int)e.Argument;
int n = 0;
indicator = false;
do
{
//write to serial writer
sw.WriteLine(serialPort1.ReadLine());
if (backgroundWorker1.CancellationPending)
{
sw.Flush();
sw.Close();
e.Cancel = true;
break;
}
// backgroundWorker1.ReportProgress(n++);
}
while (indicator ==false);
}
catch (TimeoutException)
{
//Close Serial Writer & Messagebox
//txtRead.Text = "Time Out!";
MessageBox.Show("TimeOut Exception");
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnRead.Text = "Read";
//close serial writer
}
}
}
答案 0 :(得分:0)
由于你有一个do-while构造,你可以在END评估条件!
因此,当您点击Close
按钮并关闭SerialPort时,后台工作人员仍处于活动状态并在后台运行,尝试从SerialPort
读取。它进入了do隔间并试图从一个封闭的端口读取,就像再次关闭一扇门:)这导致异常。
你可以通过
解决它 1)将while-evaluation放在最前面并删除do
语句(使其成为一个简单的while循环)。这样,serialPort.ReadLine
将不再执行,因为您在按下关闭按钮时设置了indicator = true;
。
在这种情况下,您应该在关闭端口之前将indicator
的设置作为第一行:
private void btnClose_Click(object sender, EventArgs e)
{
try
{
indicator = true;
serialPort1.Close();
或者
2)添加一个额外的if子句,确保只在端口打开时才能读取!
if (serialPort1.IsOpen)
{
sw.WriteLine(serialPort1.ReadLine());
}