阅读串行通信 Visual Studios

Reading Serial Communication Visual Studios

我需要后台工作者的帮助。我正在尝试从串行端口读取数据(使用按钮可以正常工作)问题是我需要连续从串行端口读取数据,直到有人按下表单上的按钮(关闭按钮)停止读取。我试着通过添加一个循环来做到这一点,但它只是无限地 运行 并冻结了表格。我有以下代码,每当我按下按钮读取时,都会创建一个文件,但是当我按下关闭端口按钮时,它会显示

The I/O operation has been aborted because of either a thread exit or an application request

关于如何解决这个问题有什么想法吗?

    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
    }

}

}

因为你有一个 do-while 结构,所以你在 END 评估条件! 因此,当您点击 Close 按钮并关闭 SerialPort 时,backgroundworker 仍然处于活动状态并且 运行 在后台尝试从 SerialPort 读取数据。它进入 do 隔间并尝试从关闭的端口读取,这就像 运行 又是一扇关闭的门 :) 这会导致异常。

你可以通过

解决

1) 将 while-evaluation 放在最上面并去掉 do 语句(使其成为一个简单的 while-loop)。这样 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());
}