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

C# 主線程與 Socket 子線程通訊的現代實現模式

     編輯:程式設計綜合問答

問題背景

WinForms/WPF 應用中,主線程(UI 線程)需將用戶輸入的文本發送給負責 Socket 通訊的子線程。傳統 Win32 風格使用全局變量、互斥體、事件同步,代碼冗長且易出錯。

推薦方案:BlockingCollection + Task

.NET 4.0+ 提供 System.Collections.Concurrent.BlockingCollection<T>,內部封裝了線程安全隊列與信號量,極大簡化生產者-消費者模式。

完整示例

// 主窗體類
public partial class MainForm : Form
{
    private BlockingCollection<string> _sendQueue = new BlockingCollection<string>();
    private CancellationTokenSource _cts = new CancellationTokenSource();
    private Task _socketTask;

    public MainForm()
    {
        InitializeComponent();
        _socketTask = Task.Run(() => SocketWorker(_cts.Token));
    }

    // UI 按鈕點擊:生產者
    private void btnSend_Click(object sender, EventArgs e)
    {
        string msg = txtInput.Text;
        if (!string.IsNullOrEmpty(msg))
            _sendQueue.Add(msg); // 阻塞直到隊列有空間(默認無界)
    }

    // 子線程:消費者
    private void SocketWorker(CancellationToken token)
    {
        using (var client = new TcpClient("127.0.0.1", 8888))
        using (var stream = client.GetStream())
        {
            foreach (var msg in _sendQueue.GetConsumingEnumerable(token))
            {
                byte[] data = Encoding.UTF8.GetBytes(msg);
                stream.Write(data, 0, data.Length);
            }
        }
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        _cts.Cancel();
        _sendQueue.CompleteAdding();
        _socketTask.Wait(TimeSpan.FromSeconds(2));
        base.OnFormClosing(e);
    }
}

進階:雙向通訊與 UI 更新

  • 接收數據:另開一個 BlockingCollection<string> _receiveQueue,子線程 Add,主線程用 Task.Run 輪詢 Take 並 Invoke 更新 UI。
  • 現代替代:考慮使用 System.Net.WebSockets 或 SignalR 等高層庫,自動處理重連、心跳、序列化。

為何不推薦 Win32 風格

手動管理 Mutex、Event、全局緩衝區極易導致死鎖、競態條件、內存洩漏。.NET 並發集合經過嚴格測試,性能優異且 API 簡潔。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved