C#处理二进制文件,多线程处理

Posted

技术标签:

【中文标题】C#处理二进制文件,多线程处理【英文标题】:C# Process Binary File, Multi-Thread Processing 【发布时间】:2010-04-21 09:53:43 【问题描述】:

我有以下处理二进制文件的代码。我想通过使用线程并将二进制文件的每一行分配给 ThreadPool 中的线程来拆分处理工作负载。每行的处理时间很短,但在处理可能包含数百行的文件时,拆分工作负载是有意义的。

我的问题是关于 BinaryReader 和线程安全。首先,我正在做的事情是可以接受的。我感觉最好只将每行的二进制文件传递给 PROCESS_Binary_Return_lineData 方法。

请注意下面的代码是概念性的。我正在寻找这方面的一些指导,因为我对多线程的了解还处于起步阶段。或许有更好的方法可以达到同样的效果,即对每条二进制行进行拆分处理。

        var dic = new Dictionary<DateTime, Data>();        
        var resetEvent = new ManualResetEvent(false);

        using (var b = new BinaryReader(File.Open(Constants.dataFile, 
                            FileMode.Open, FileAccess.Read, FileShare.Read)))
        
        var lByte = b.BaseStream.Length;
        var toProcess = 0;

        while (lByte >= DATALENGTH)
        
            b.BaseStream.Position = lByte;
            lByte = lByte - AB_DATALENGTH;

            ThreadPool.QueueUserWorkItem(delegate
            
                Interlocked.Increment(ref toProcess);
                var lineData = PROCESS_Binary_Return_lineData(b);

                lock(dic)
                
                    if (!dic.ContainsKey(lineData.DateTime))
                    
                     dic.Add(lineData.DateTime, lineData); 
                    
                

                if (Interlocked.Decrement(ref toProcess) == 0) resetEvent.Set();
            , null);
        
        

        resetEvent.WaitOne();

【问题讨论】:

【参考方案1】:

这对我来说看起来不是线程安全的。如果您有多个工作项排队,并且其中两个恰好同时运行,则阅读器的位置很容易在分配和阅读之间改变。

如果您坚持为此使用线程,您最好在主线程中读取数据并将生成的字节数组排队以供读取。任何涉及从文件中读取每个线程的解决方案都将涉及锁定,此时,您根本无法从使用线程中获得任何收益。

【讨论】:

会是由以下方式派生的字节数组: - var LineBytes = b.ReadBytes(DATALENGTH);还是我必须将数据克隆到字节数组以确保它不再引用文件流。 您应该能够使用 b.ReadBytes(DATALENGTH) 的结果。【参考方案2】:

很少使用线程来提高文件处理性能。线程在多核 CPU 上运行时,会提供更多的 CPU 周期。这很少是您在处理文件时缺少的资源。您需要更多磁盘。当然不是一个选项。

首先进行烟雾测试。重新启动您的机器,这样文件就不会存储在文件系统缓存中。运行单线程程序并观察 CPU 负载。 Taskmgr.exe,性能选项卡对此很有用。如果您没有看到一个 CPU 在 100% 负载时达到最大值,那么添加另一个 CPU 不会让您的程序更快。

【讨论】:

【参考方案3】:

“我有一种感觉会更好 只传递每行的二进制文件 到 PROCESS_Binary_Return_lineData 方法。”

是的,您需要这样做,因为您的委托可能无法在 BinaryReader 重新定位之前读取它

【讨论】:

以上是关于C#处理二进制文件,多线程处理的主要内容,如果未能解决你的问题,请参考以下文章

删除 C# 二进制文件中未使用的预处理器符号

C# 怎么处理Word文件的乱码

C-进制,多文件开发,预处理,地址

如何高效地处理数百个项目中的数千个 C# 文件?

C# 检查文件的二进制读取器结尾

C#字节数组的常用解码处理方法