阅读串行通信视觉工作室

时间:2017-07-28 13:03:13

标签: c# visual-studio-2010 serial-port backgroundworker serial-communication

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

  

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
    }

}

}

1 个答案:

答案 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());
}