每日财经早报排名优化网站
方案核心思路
-
写入请求队列:使用
ConcurrentQueue
接收来自任意线程的写入请求。 -
专用写入线程:由独立线程处理队列中的写入操作,确保顺序执行。
-
双信号机制:通过
ManualResetEventSlim
控制读取线程的暂停与恢复。 -
线程安全确认:确保多个线程同时触发写入时,不会导致竞态条件。
完整代码实现
using System;
using System.Collections.Concurrent;
using System.Threading;public class CrossThreadReadWriteController
{// 控制读取线程暂停和恢复的信号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();}// 读取线程的循环任务public void ReadLoop(){while (!_stopRequested){// 检查是否需要暂停if (_pauseRequest.IsSet){// 确认已暂停,并等待恢复信号_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)){// 触发暂停读取线程RequestPause();// 执行写入操作writeAction.Invoke();// 恢复读取线程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(); // 等待读取线程确认暂停}// 恢复读取线程(线程安全)private void ResumeRead(){_pauseRequest.Reset();}// 停止所有线程public void Stop(){_stopRequested = true;_pauseRequest.Set(); // 确保读取线程退出等待_writeThread.Join(); // 等待写入线程结束}
}// 使用示例
public class Program
{public static void Main(){var controller = new CrossThreadReadWriteController();// 启动读取线程var readThread = new Thread(controller.ReadLoop);readThread.Start();// 模拟多个线程触发写入操作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.");}
}
关键改进解析
1. 跨线程写入请求的提交
通过 SubmitWriteCommand
方法,任何线程均可提交写入操作:
public void SubmitWriteCommand(Action writeAction)
{_writeQueue.Enqueue(writeAction); // 线程安全入队
}
2. 专用写入线程处理队列
写入操作由独立线程顺序处理,避免多线程并发写入冲突:
private void ProcessWriteQueue()
{while (!_stopRequested || !_writeQueue.IsEmpty){if (_writeQueue.TryDequeue(out var writeAction)){RequestPause(); // 暂停读取线程writeAction(); // 执行写入ResumeRead(); // 恢复读取线程}}
}
3. 双重信号确保原子性
通过 RequestPause
和 ResumeRead
方法封装暂停与恢复逻辑:
private void RequestPause()
{_pauseRequest.Set(); // 发送暂停信号_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.
方案优势
特性 | 说明 |
---|---|
多线程安全 | 通过 ConcurrentQueue 和信号量,支持任意线程触发写入操作。 |
顺序执行 | 写入操作由专用线程顺序处理,避免并发冲突。 |
无锁读取 | 读取线程在非写入状态下完全无锁,最大化性能。 |
精准控制 | 通过双信号机制确保写入操作执行期间读取线程完全暂停。 |
适用场景
-
分布式任务调度:多个工作线程提交写入请求,由中心线程处理。
-
实时数据采集:采集线程持续读取数据,外部线程动态更新配置。
-
高并发服务:如网络服务器,处理来自不同客户端的并发更新操作。
注意事项
-
队列积压风险:若写入操作频率过高,需监控队列长度或添加背压机制。
-
异常处理:在写入操作中需捕获异常,避免导致写入线程崩溃。
-
性能调优:可根据场景调整
Thread.Sleep
时间或使用无等待策略。