简体   繁体   English

读取串行通信Visual Studios

[英]Reading Serial Communication Visual Studios

I need some help with Background worker. 我需要背景工作者的帮助。 I am trying to read data from a serial port (works fine with a button) the problem is that I need to continuously read from the serial port, until someone presses a button (Close button) on the form to stop reading. 我正在尝试从串行端口读取数据(可以通过按钮正常工作),问题是我需要不断从串行端口读取数据,直到有人按下表单上的按钮(关闭按钮)以停止读取为止。 I tried doing this by adding a loop, but it just ran infinitely and froze up the form. 我尝试通过添加一个循环来执行此操作,但是它无限运行并冻结了表单。 I have the following code, whenever I press the button to read, a file is created, but when I press the close port button,it says 我有以下代码,每当我按下按钮进行读取时,都会创建一个文件,但是当我按下关闭端口按钮时,它会说

The I/O operation has been aborted because of either a thread exit or an application request 由于线程退出或应用程序请求,I / O操作已中止

Any ideas on how to fix this? 有想法该怎么解决这个吗?

    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
    }

}

} }

Since you have a do-while construct you evaluate the condition at the END! 由于您具有do-while构造,因此可以在END评估条件! So when you hit the Close button and close the SerialPort the backgroundworker is still active and running in the background trying to read from the SerialPort . 因此,当您单击“ Close按钮并关闭SerialPort时,backgroundworker仍处于活动状态并在后台运行,试图从SerialPort读取数据。 It enters the do compartment and tries to read from a closed port, which is like running agains a closed door :) this leads to the exception. 它进入do隔间并尝试从关闭的端口读取数据,就像再次在关闭的门上运行:)那样会导致异常。

You could solve it by 你可以通过解决

1) putting the while-evaluation on top and get rid of the do statement (making it a simple while-loop). 1)将while评估放在最前面并摆脱do语句(使其成为一个简单的while循环)。 This way the serialPort.ReadLine will not be executed anymore, because you set indicator = true; 这样,不再执行serialPort.ReadLine ,因为您设置了indicator = true; when hitting the close button. 点击关闭按钮时。

May be in this case you should put the setting of indicator as the first line before closing the port: 在这种情况下,可能应该在关闭端口之前将indicator的设置作为第一行:

private void btnClose_Click(object sender, EventArgs e)
{
    try
    {
        indicator = true;
        serialPort1.Close();

Or 要么

2) put an extra if clause that makes sure to read only if the port is open! 2)放置一个额外的if子句,以确保仅在端口打开时才能读取!

if (serialPort1.IsOpen)
{
    sw.WriteLine(serialPort1.ReadLine());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM