WinForms/WPF 應用中,主線程(UI 線程)需將用戶輸入的文本發送給負責 Socket 通訊的子線程。傳統 Win32 風格使用全局變量、互斥體、事件同步,代碼冗長且易出錯。
.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);
}
}
BlockingCollection<string> _receiveQueue,子線程 Add,主線程用 Task.Run 輪詢 Take 並 Invoke 更新 UI。System.Net.WebSockets 或 SignalR 等高層庫,自動處理重連、心跳、序列化。手動管理 Mutex、Event、全局緩衝區極易導致死鎖、競態條件、內存洩漏。.NET 並發集合經過嚴格測試,性能優異且 API 簡潔。