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

