简体   繁体   English

多线程 C# serialPort1_DataReceived 事件不触发

[英]Multithread C# serialPort1_DataReceived event does not fire

I read/write data to serial port and I want to see reading on listbox right away.我将数据读/写到串行端口,我想立即在列表框中看到读数。 I created a new thread to send command to serial port.我创建了一个新线程来向串口发送命令。 I keep the main thread empty, so, it can update the UI and also serial port event handler wont be interrupted with something else.(I am not sure is it right approach?)我将主线程保持为空,因此它可以更新 UI,并且串行端口事件处理程序也不会被其他东西中断。(我不确定这是正确的方法吗?)

The following code works with while (.dataRecieved) { Thread;Sleep(4000); }以下代码适用于while (.dataRecieved) { Thread;Sleep(4000); } while (.dataRecieved) { Thread;Sleep(4000); } but does not works with while (.dataRecieved) { Thread;Sleep(100); } while (.dataRecieved) { Thread;Sleep(4000); }但不适用于while (.dataRecieved) { Thread;Sleep(100); } while (.dataRecieved) { Thread;Sleep(100); } . while (.dataRecieved) { Thread;Sleep(100); } The problem is if I use 100ms sleep, serial port event handler fire only once and then program stops.(If I debug with breakpoint 100ms works because I create additional time when stepping into the code.) If I wait 4000ms the program works, Also.问题是如果我使用 100 毫秒睡眠,串行端口事件处理程序只触发一次然后程序停止。(如果我使用断点 100 毫秒进行调试,因为我在进入代码时创建了额外的时间。)如果我等待 4000 毫秒,程序也可以工作. I check the time between sending data and receiving data from serial port is 200ms, So.我检查从串口发送数据和接收数据之间的时间是200ms,所以。 100ms is reasonable. 100ms 是合理的。

Here is the code:这是代码:

public bool dataRecieved = false;

public Form1()
        {
            InitializeComponent();
        }

        public void AppendTextBox(string value)
        {
            this.Invoke((MethodInvoker)delegate { richTextBox1.Text += value + "\n";});
        }

private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.Open();
            Thread testThread = new Thread(() => sendThread());
            testThread.Start();
        }

public void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            data = serialPort1.ReadLine();
            dataRecieved = true;
        }

public void sendThread()
        {
            for(int i = 0; i<10; i++) 
            {
              serialPort1.WriteLine("AT" + i);
              // Following line creates odd situation:
              // if Thread.Sleep(100), I receive only first data, then program stops(serial port handler doesnt fire!).
              // if Thread.Sleep(4000), I receive all data, successfuly works.
              // But I do not want to wait 4000ms, because I receive answer from device in 200ms.
              while (!dataRecieved) { Thread.Sleep(100); }
              AppendTextBox("Received" + "AT" + i);
              dataRecieved = false;
            }
        } 

Where I am wrong?我哪里错了? Can you please provide a solution?你能提供一个解决方案吗?

I even didn't use a new Thead for write and read on SerialPort.我什至没有使用新的 Thead 在 SerialPort 上进行读写。 You just need use update control in Invoke() is ok.你只需要在 Invoke() 中使用更新控件就可以了。 Below is my update on richTextBox.下面是我对richTextBox 的更新。 You can change form richTextBox to your listbox.您可以将表单richTextBox 更改为您的列表框。

 public void update_RichTextBox(string message)
        {
            Invoke(new System.Action(() =>
            {
                txtReceivedData.Text += message;
                txtReceivedData.Refresh();
                txtReceivedData.SelectionStart = txtReceivedData.Text.Length;
                txtReceivedData.ScrollToCaret();
            }));
            
        }

and the way to use above void:以及上面void的使用方式:

if (ComPort.IsOpen)
  {
                ComPort.Write(_inputdata + "\r");
                Form1._Form1.update_RichTextBox(_inputdata + "\r");
                string _receviedData = ComPort.ReadExisting();
                Form1._Form1.update_RichTextBox(respond);
                ComPort.DiscardInBuffer();//delete all data in device's received buffer
                ComPort.DiscardOutBuffer();// delete all data in transmit buffer
  }
else
            {
                MessageBox.Show("haven't yet open COM port");
                return "FLASE";
            }

I use something I call "Cross Thread Linker"我使用我称之为“跨线程链接器”的东西

#region Cross Thread Linker
public bool ControlInvokeRequired(Control c, Action a)
{
    if (c.InvokeRequired) c.Invoke(new MethodInvoker(delegate { a(); }));
    else return false;
    return true;
}

void Update_RichTextBox(RichTextBox rtb, string Text)
{
    if (ControlInvokeRequired(rtb, () => Update_RichTextBox(rtb, Text))) return;
    rtb.AppendText(Text + Environment.NewLine);
}

#endregion

Then:然后:

Update_RichTextBox(richTextBox1, "Text to append");

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

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