首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 多項目解耦:SerialPort 邏輯分離與事件回調模式

     編輯:程式設計綜合問答

架構演進

單項目時: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("准備掃描"); // 觸發事件
        }
    }
}

UI 項目:訂閱事件

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
    }
}

關鍵優勢

  • 解耦:類庫零依賴 UI,可復用於 WPF、Console、Service 等宿主。
  • 線程安全:事件在 IO 線程觸發,UI 端統一 Invoke 處理跨線程調用。
  • 可測試:單元測試可直接模擬觸發事件,無需真實串口。

進階擴展

  • 定義 EventArgs 傳遞結構化數據(原始字節、解析後命令、時間戳)。
  • 實現 IObservable<T> 支援 Reactive Extensions (Rx) 鏈式處理。
  • 添加連接狀態變更、錯誤事件,構建完整狀態機。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved