單項目時:UI 直接訂閱 SerialPort.DataReceived,回調中跨線程更新控件(需 Invoke)。
拆分項目後:SerialPort 邏輯移至獨立類庫,UI 項目引用類庫。若類庫直接引用 UI 會產生循環依賴。
public class SerialPortService {
public event Action<string> DataReceived; // 公開事件
private SerialPort _port;
public void Start(string portName) {
_port = new SerialPort(portName, 9600);
_port.DataReceived += OnDataReceived;
_port.Open();
}
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e) {
string data = _port.ReadExisting();
if (data.Contains("0B")) {
DataReceived?.Invoke("准備掃描"); // 觸發事件
}
}
}
public partial class MainForm : Form {
private SerialPortService _serialService;
public MainForm() {
InitializeComponent();
_serialService = new SerialPortService();
_serialService.DataReceived += OnSerialDataReceived; // 訂閱
_serialService.Start("COM1");
}
private void OnSerialDataReceived(string message) {
if (InvokeRequired) {
Invoke(new Action<string>(OnSerialDataReceived), message);
return;
}
lblStatus.Text = message; // 安全更新 UI
}
}
Invoke 處理跨線程調用。EventArgs 傳遞結構化數據(原始字節、解析後命令、時間戳)。IObservable<T> 支援 Reactive Extensions (Rx) 鏈式處理。