錯誤代碼
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) {
// ...
PowerMainForm pf = new PowerMainForm(); // 錯誤:創建新實例
pf.setValue(); // 修改的是新實例的控件,主窗口無變化
}
原因
DataReceived 在**線程池線程**觸發,非 UI 線程。
new PowerMainForm() 創建的是**全新窗口實例**,與運行中的主窗口無關。
- 直接操作控件屬性跨線程非法(.NET 2.0+ 默認檢查
Control.CheckForIllegalCrossThreadCalls)。
正確模式
public partial class PowerMainForm : Form {
// 構造器傳入串口實例或靜態引用主窗口
public PowerMainForm() { InitializeComponent(); }
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) {
byte[] buf = new byte[serialPort1.BytesToRead];
serialPort1.Read(buf, 0, buf.Length);
string data = Encoding.ASCII.GetString(buf);
// 線程安全調用 UI
this.Invoke((Action)(() => {
if (data.Contains("OA")) {
label21.Text = "aa";
label23.Visible = true;
}
}));
}
}
關鍵點
- 使用
Control.Invoke/BeginInvoke 將委托發送到 UI 線程執行。
- 串口對象應為主窗口成員,事件處理器內部直接
this.Invoke。|