代表和跨线程异常

0co*_*ool 3 c# multithreading delegates

每当我使用委托更新Windows窗体中的UI时,它会给我跨线程异常,为什么会发生这种情况?是否为每个代表调用启动了新线程?

void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
       //this call delegate to display data
       clsConnect(statusMsg);
}




 protected void displayResponse(string resp)
 {
     //here cross thread exception occur if directly set to lblMsgResp.Text="Test";
     if (lblMsgResp.InvokeRequired)
     {
        lblMsgResp.Invoke(new MethodInvoker(delegate { lblMsgResp.Text = resp; }));
     }
 }
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 5

DataReceived事件始终在线程池线程上引发.您无法更新任何UI控件,您必须使用Control.BeginInvoke().没有必要测试InvokeRequired,它总是如此.

这里要记住几件事:

  • 不要为您收到的每个字符或字节调用Control.BeginInvoke.这将使UI线程陷入困境.缓冲从串行端口获得的数据,直到获得完整的响应.使用SerialPort.ReadLine()通常运行良好,许多设备发送由换行符(SerialPort.NewLine)终止的字符串.
  • 关闭程序可能很困难.您必须确保表单保持活动状态,直到串行端口停止发送.在窗体关闭后获取事件将生成ObjectDisposed异常.使用FormClosing事件关闭串行端口并启动一秒计时器.只有在计时器到期时才真正关闭表单.
  • 避免使用Control.Invoke而不是BeginInvoke.调用SerialPort.Close()时,它可能会使程序死锁.

有很多方法可以解决问题.考虑使用您自己的线程,而不是使用DataReceived来避免它们.