2

我有以下处理二进制文件的代码。我想通过使用线程并将二进制文件的每一行分配给 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();
4

3 回答 3

3

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

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

于 2010-04-21T10:09:49.663 回答
2

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

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

于 2010-04-21T12:57:22.453 回答
0

“我觉得最好只将每行的二进制文件传递给 PROCESS_Binary_Return_lineData 方法。”

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

于 2010-04-21T10:09:32.640 回答