1

我有多个串行设备连接到我的 PC,我正在开发一个程序,该程序允许用户选择他们想要的任意数量的端口,然后程序将动态创建TabPage并将它们添加到TabControl.

每个标签页还将有一个多行TextBox显示从分配的串行端口到它的传入数据。

这是我尝试动态创建这些控件的代码:

private void AddSerialPort(string portName)
{
    ActiveSerialPorts.Add(portName);

    if (!tabControlActiveSerialPorts.Enabled)
        tabControlActiveSerialPorts.Enabled = true;

    var page = new TabPage(portName);

    page.Text = portName;

    var tb = new TextBox();
    tb.Name = portName;
    tb.Dock = DockStyle.Fill;
    tb.BackColor = Color.Black;
    tb.Multiline = true;
    page.Controls.Add(tb);
    tabControlActiveSerialPorts.TabPages.Add(page);


    var sp = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One);
    sp.Open();
    tb.Tag = sp;
    sp.DataReceived += delegate
                        {
                            tb.Text += sp.ReadExisting(); //LINE 87
                        };
}

问题:这是我在运行时遇到的错误,并在第 87 行 中断(对上面的代码进行了评论):

Cross-thread operation not valid: Control 'COM16' accessed from a thread other than the thread it was created on.

这里可能存在什么陷阱?

4

1 回答 1

1

您正在后台线程上接收数据并尝试从非 UI 线程更新 UI。您需要将数据从后台线程编组到 UI 线程以更新控件。这可以使用Control.Invoke方法来完成。

sp.DataReceived += delegate 
     {
         if (tb.InvokeRequired)
         {
            tb.Invoke(new Action(() =>
            {
                tb.Text += sp.ReadExisting(); 
            }));
         }
         else
         {
            tb.Text += sp.ReadExisting(); 
         }
     }
于 2013-06-04T12:36:57.657 回答