C#中实现跨线程写入的示例代码

 更新时间:2026年01月09日 11:26:31   作者:就是有点傻  
本文主要介绍了C#中实现跨线程写入的示例代码,通过ConcurrentQueue接收写入请求,由专用线程顺序处理,并使用双信号机制控制读取线程的暂停与恢复,下面就来详细的介绍一下

方案核心思路

  • 写入请求队列:使用 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 时间或使用无等待策略。

到此这篇关于C#中实现跨线程写入的示例代码的文章就介绍到这了,更多相关C# 跨线程写入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • WPF实现窗体亚克力效果的示例代码

    WPF实现窗体亚克力效果的示例代码

    这篇文章主要为大家详细介绍了如何利用WPF实现窗体亚克力效果,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
    2022-10-10
  • C# FileStream简单介绍和使用

    C# FileStream简单介绍和使用

    这篇文章主要为大家详细介绍了C# FileStream基本功能和使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • c# AcceptEx与完成端口(IOCP)结合的示例

    c# AcceptEx与完成端口(IOCP)结合的示例

    这篇文章主要介绍了c# AcceptEx与完成端口(IOCP)结合的示例,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • c# 判断是否为空然后赋值的4种实现方法

    c# 判断是否为空然后赋值的4种实现方法

    下面小编就为大家分享一篇c# 判断是否为空然后赋值的4种实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C# winform点击生成二维码实例代码

    C# winform点击生成二维码实例代码

    这篇文章主要介绍了 C# winform点击生成二维码实例代码,需要的朋友可以参考下
    2017-04-04
  • C# WinForm调用Shell_NotifyIcon的示例代码

    C# WinForm调用Shell_NotifyIcon的示例代码

    这篇文章主要介绍了C# WinForm调用Shell_NotifyIcon的示例代码,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-11-11
  • WPF实现动画效果(七)之演示图板

    WPF实现动画效果(七)之演示图板

    这篇文章介绍了WPF实现动画效果之演示图板,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 利用C#在PDF文档中添加电子签名的实现流程

    利用C#在PDF文档中添加电子签名的实现流程

    电子签名在文档合规性与安全性保障中扮演着重要角色,基于 C# 开发 PDF 电子签名功能是企业级文档处理场景的常见需求,Spire.PDF for .NET 作为国产 PDF 处理类库,无需依赖 Adobe Acrobat 等第三方软件,即可便捷实现 PDF 电子签名添加,本文为大家详细介绍一下
    2025-12-12
  • Entity Framework代码优先(Code First)模式

    Entity Framework代码优先(Code First)模式

    这篇文章介绍了Entity Framework代码优先(Code First)模式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • 使用C#将Excel导出为DataTable的实战指南

    使用C#将Excel导出为DataTable的实战指南

    在当今的数据驱动时代,Excel作为一种普遍的数据存储和交换格式,几乎无处不在,对于C#开发者而言,如何高效、便捷地将Excel文件中的数据整合到应用程序中进行处理,常常是一个需要面对的挑战,本文将介绍一种强大而易用的解决方案轻松实现Excel到DataTable的转换
    2025-10-10

最新评论