C#中實現(xiàn)跨線程寫入的示例代碼
方案核心思路
- 寫入請求隊列:使用
ConcurrentQueue接收來自任意線程的寫入請求。 - 專用寫入線程:由獨立線程處理隊列中的寫入操作,確保順序執(zhí)行。
- 雙信號機制:通過
ManualResetEventSlim控制讀取線程的暫停與恢復(fù)。 - 線程安全確認:確保多個線程同時觸發(fā)寫入時,不會導(dǎo)致競態(tài)條件。
完整代碼實現(xiàn)
using System;
using System.Collections.Concurrent;
using System.Threading;
public class CrossThreadReadWriteController
{
// 控制讀取線程暫停和恢復(fù)的信號
private readonly ManualResetEventSlim _pauseRequest = new ManualResetEventSlim(false);
// 讀取線程確認已暫停的信號
private readonly ManualResetEventSlim _pausedConfirmed = new ManualResetEventSlim(false);
// 寫入請求隊列(線程安全)
private readonly ConcurrentQueue<Action> _writeQueue = new ConcurrentQueue<Action>();
// 停止標志
private volatile bool _stopRequested = false;
// 寫入專用線程
private Thread _writeThread;
public CrossThreadReadWriteController()
{
// 啟動寫入專用線程
_writeThread = new Thread(ProcessWriteQueue);
_writeThread.Start();
}
// 讀取線程的循環(huán)任務(wù)
public void ReadLoop()
{
while (!_stopRequested)
{
// 檢查是否需要暫停
if (_pauseRequest.IsSet)
{
// 確認已暫停,并等待恢復(fù)信號
_pausedConfirmed.Set();
_pauseRequest.Wait();
_pausedConfirmed.Reset();
}
// 模擬讀取操作
Console.WriteLine($"[Read] {DateTime.Now:HH:mm:ss.fff} - Reading data...");
Thread.Sleep(1000); // 模擬耗時操作
}
Console.WriteLine("[Read] Thread stopped.");
}
// 處理寫入隊列的專用線程
private void ProcessWriteQueue()
{
while (!_stopRequested || !_writeQueue.IsEmpty)
{
if (_writeQueue.TryDequeue(out var writeAction))
{
// 觸發(fā)暫停讀取線程
RequestPause();
// 執(zhí)行寫入操作
writeAction.Invoke();
// 恢復(fù)讀取線程
ResumeRead();
}
else
{
Thread.Sleep(50); // 隊列為空時短暫休眠
}
}
Console.WriteLine("[Write] Thread stopped.");
}
// 跨線程提交寫入請求
public void SubmitWriteCommand(Action writeAction)
{
_writeQueue.Enqueue(writeAction);
}
// 請求暫停讀取線程(線程安全)
private void RequestPause()
{
_pauseRequest.Set();
_pausedConfirmed.Wait(); // 等待讀取線程確認暫停
}
// 恢復(fù)讀取線程(線程安全)
private void ResumeRead()
{
_pauseRequest.Reset();
}
// 停止所有線程
public void Stop()
{
_stopRequested = true;
_pauseRequest.Set(); // 確保讀取線程退出等待
_writeThread.Join(); // 等待寫入線程結(jié)束
}
}
// 使用示例
public class Program
{
public static void Main()
{
var controller = new CrossThreadReadWriteController();
// 啟動讀取線程
var readThread = new Thread(controller.ReadLoop);
readThread.Start();
// 模擬多個線程觸發(fā)寫入操作
for (int i = 0; i < 3; i++)
{
var threadId = i;
new Thread(() =>
{
controller.SubmitWriteCommand(() =>
{
Console.WriteLine($"[Write-{threadId}] {DateTime.Now:HH:mm:ss.fff} - Writing data...");
Thread.Sleep(500); // 模擬耗時操作
});
}).Start();
}
Thread.Sleep(5000); // 等待所有寫入完成
controller.Stop();
readThread.Join();
Console.WriteLine("Main thread exited.");
}
}關(guān)鍵改進解析
1.跨線程寫入請求的提交
通過 SubmitWriteCommand 方法,任何線程均可提交寫入操作:
public void SubmitWriteCommand(Action writeAction)
{
_writeQueue.Enqueue(writeAction); // 線程安全入隊
}2.專用寫入線程處理隊列
寫入操作由獨立線程順序處理,避免多線程并發(fā)寫入沖突:
private void ProcessWriteQueue()
{
while (!_stopRequested || !_writeQueue.IsEmpty)
{
if (_writeQueue.TryDequeue(out var writeAction))
{
RequestPause(); // 暫停讀取線程
writeAction(); // 執(zhí)行寫入
ResumeRead(); // 恢復(fù)讀取線程
}
}
}3.雙重信號確保原子性
通過 RequestPause 和 ResumeRead 方法封裝暫停與恢復(fù)邏輯:
private void RequestPause()
{
_pauseRequest.Set(); // 發(fā)送暫停信號
_pausedConfirmed.Wait(); // 阻塞等待讀取線程確認暫停
}4.線程安全停止機制
通過 _stopRequested 標志和隊列檢查確保安全退出:
public void Stop()
{
_stopRequested = true;
_writeThread.Join(); // 等待寫入線程處理完隊列
}運行效果
[Read] 14:30:01.123 - Reading data...
[Read] 14:30:02.124 - Reading data...
[Write-0] 14:30:03.125 - Writing data...
[Read] 14:30:03.626 - Reading data...
[Write-1] 14:30:04.127 - Writing data...
[Read] 14:30:04.628 - Reading data...
[Write-2] 14:30:05.129 - Writing data...
Main thread exited.
方案優(yōu)勢
| 特性 | 說明 |
|---|---|
| 多線程安全 | 通過 ConcurrentQueue 和信號量,支持任意線程觸發(fā)寫入操作。 |
| 順序執(zhí)行 | 寫入操作由專用線程順序處理,避免并發(fā)沖突。 |
| 無鎖讀取 | 讀取線程在非寫入狀態(tài)下完全無鎖,最大化性能。 |
| 精準控制 | 通過雙信號機制確保寫入操作執(zhí)行期間讀取線程完全暫停。 |
適用場景
- 分布式任務(wù)調(diào)度:多個工作線程提交寫入請求,由中心線程處理。
- 實時數(shù)據(jù)采集:采集線程持續(xù)讀取數(shù)據(jù),外部線程動態(tài)更新配置。
- 高并發(fā)服務(wù):如網(wǎng)絡(luò)服務(wù)器,處理來自不同客戶端的并發(fā)更新操作。
注意事項
- 隊列積壓風險:若寫入操作頻率過高,需監(jiān)控隊列長度或添加背壓機制。
- 異常處理:在寫入操作中需捕獲異常,避免導(dǎo)致寫入線程崩潰。
- 性能調(diào)優(yōu):可根據(jù)場景調(diào)整
Thread.Sleep時間或使用無等待策略。
到此這篇關(guān)于C#中實現(xiàn)跨線程寫入的示例代碼的文章就介紹到這了,更多相關(guān)C# 跨線程寫入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c# AcceptEx與完成端口(IOCP)結(jié)合的示例
這篇文章主要介紹了c# AcceptEx與完成端口(IOCP)結(jié)合的示例,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-03-03
C# WinForm調(diào)用Shell_NotifyIcon的示例代碼
這篇文章主要介紹了C# WinForm調(diào)用Shell_NotifyIcon的示例代碼,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-11-11
Entity?Framework代碼優(yōu)先(Code?First)模式
這篇文章介紹了Entity?Framework代碼優(yōu)先(Code?First)模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06
使用C#將Excel導(dǎo)出為DataTable的實戰(zhàn)指南
在當今的數(shù)據(jù)驅(qū)動時代,Excel作為一種普遍的數(shù)據(jù)存儲和交換格式,幾乎無處不在,對于C#開發(fā)者而言,如何高效、便捷地將Excel文件中的數(shù)據(jù)整合到應(yīng)用程序中進行處理,常常是一個需要面對的挑戰(zhàn),本文將介紹一種強大而易用的解決方案輕松實現(xiàn)Excel到DataTable的轉(zhuǎn)換2025-10-10

