0

0

C#处理高并发文件写入 C#如何设计一个高吞吐量的文件写入队列

畫卷琴夢

畫卷琴夢

发布时间:2026-02-28 08:40:03

|

532人浏览过

|

来源于php中文网

原创

高并发下 filestream.write 崩溃主因是内核句柄竞争、i/o 阻塞与磁盘寻道放大;streamwriter 非线程安全易致异常或数据错乱;推荐 concurrentqueue + 后台线程批量刷盘解耦生产消费,兼顾性能与稳定性。

c#处理高并发文件写入 c#如何设计一个高吞吐量的文件写入队列

为什么直接 FileStream.Write 在高并发下会崩

多个线程同时调用 FileStream.Write 写同一个文件,哪怕加了 lock,也会因频繁的 I/O 阻塞、内核句柄竞争和磁盘寻道放大延迟,吞吐迅速跌穿 1MB/s。更糟的是,StreamWriter 默认带缓冲但非线程安全,跨线程写入可能触发 ObjectDisposedException 或数据错乱。

  • Windows 上对同一文件的并发 WriteFile 调用会被串行化,本质仍是单点瓶颈
  • 每次写入都触发一次系统调用,上下文切换成本在万级 QPS 下不可忽略
  • 小块写入(如每条日志几十字节)会激增磁盘 I/O 次数,SSD 寿命和延迟双受损

ConcurrentQueue + 后台写入线程是最稳的起点

核心思路是解耦“生产”和“消费”:业务线程只往线程安全队列投递数据,由单一后台线程批量刷盘。这避免锁争用,也天然聚合小写请求。

  • ConcurrentQueue<string></string>ConcurrentQueue<byte></byte> 存原始数据,比 BlockingCollection 更轻量(后者含额外同步开销)
  • 后台线程用 Thread.Sleep(1)SpinWait.SpinOnce() 等待,别用 BlockingCollection.Take() —— 它在空时仍会进内核态,增加延迟
  • 攒够阈值(如 8KB 或 100 条)再刷盘,或每 10ms 强制 flush 一次,防消息积压过久
var queue = new ConcurrentQueue<byte[]>();
Task.Run(() => {
    var buffer = new List<byte[]>(128);
    while (!cancellationToken.IsCancellationRequested) {
        if (queue.TryDequeue(out var item)) {
            buffer.Add(item);
            if (buffer.Sum(b => b.Length) >= 8192) Flush(buffer);
        } else if (buffer.Count > 0) {
            Flush(buffer);
        } else {
            Thread.Sleep(1); // 低频轮询,避免 CPU 空转
        }
    }
});

MemoryMappedFile 适合超大吞吐但代价高

当单机写入持续超过 500MB/s(如金融行情快照),纯队列模型可能因内存拷贝和 GC 压力成为瓶颈。MemoryMappedFile 可绕过 .NET 堆,让多线程直接写共享内存页,再由独立线程调用 FlushViewOfFile 刷盘。

Shell脚本编写基础 中文WORD版
Shell脚本编写基础 中文WORD版

Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统

下载
  • 必须用 FileOptions.RandomAccess | FileOptions.WriteThrough 创建映射,禁用系统缓存,避免 double-buffering
  • 需自行管理写位置指针(long 类型原子变量),并处理跨页边界——写到页尾要手动切到下一页
  • 崩溃恢复难:映射文件不保证落盘顺序,断电可能丢最后几页数据,必须配 CRC 校验和 checkpoint 机制

别忽略 FileOptions.AsynchronousWriteAsync

如果写入目标是网络文件系统(如 SMB 共享)或云存储网关,同步 I/O 会卡死整个线程池。此时应改用异步流,但要注意陷阱:

  • FileStream 必须用 FileOptions.Asynchronous 构造,否则 WriteAsync 内部仍走同步路径
  • 不要在 async void 方法里写日志,异常会静默丢失;统一用 async Task 并 await
  • 并发 WriteAsync 到同一文件仍需锁(如 SemaphoreSlim),但锁粒度可缩小到单次 write 调用,而非整条消息

真正难的不是堆砌技术,而是确定你的瓶颈在哪——是磁盘吞吐?CPU 序列化?还是网络延迟?先用 PerfView 抓一下 ThreadPoolIO 的热区,再决定上 MemoryMappedFile 还是老实用队列。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

105

2025.10.23

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

185

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

125

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

428

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

599

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

428

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

599

2023.08.10

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

2

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 10.4万人学习

C 教程
C 教程

共75课时 | 5万人学习

C++教程
C++教程

共115课时 | 19.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号