c# - 并行读取和处理文件 C#

标签 c# multithreading

我有非常大的文件需要阅读和处理。这可以使用线程并行完成吗?

这是我完成的一些代码。但是一个接一个地读取和处理文件似乎并没有缩短执行时间。

String[] files = openFileDialog1.FileNames;

Parallel.ForEach(files, f =>
{
    readTraceFile(f);
});        

private void readTraceFile(String file)
{
    StreamReader reader = new StreamReader(file);
    String line;

    while ((line = reader.ReadLine()) != null)
    {
        String pattern = "\\s{4,}";

        foreach (String trace in Regex.Split(line, pattern))
        {
            if (trace != String.Empty)
            {
                String[] details = Regex.Split(trace, "\\s+");

                Instruction instruction = new Instruction(details[0],
                    int.Parse(details[1]),
                    int.Parse(details[2]));
                Console.WriteLine("computing...");
                instructions.Add(instruction);
            }
        }
    }
}

最佳答案

看起来您的应用程序的性能主要受 IO 限制。但是,您的代码中仍有一些 CPU 密集型工作。这两部分工作是相互依赖的:在 IO 完成其工作之前,您的 CPU 密集型工作无法开始,并且在您的 CPU 完成前一个工作之前,IO 不会移动到下一个工作项目。他们都在互相扶持。因此,可能(在最底部解释)如果您并行执行 IO 和 CPU 绑定(bind)工作,您将看到吞吐量的提高,如下所示:

void ReadAndProcessFiles(string[] filePaths)
{
    // Our thread-safe collection used for the handover.
    var lines = new BlockingCollection<string>();

    // Build the pipeline.
    var stage1 = Task.Run(() =>
    {
        try
        {
            foreach (var filePath in filePaths)
            {
                using (var reader = new StreamReader(filePath))
                {
                    string line;

                    while ((line = reader.ReadLine()) != null)
                    {
                        // Hand over to stage 2 and continue reading.
                        lines.Add(line);
                    }
                }
            }
        }
        finally
        {
            lines.CompleteAdding();
        }
    });

    var stage2 = Task.Run(() =>
    {
        // Process lines on a ThreadPool thread
        // as soon as they become available.
        foreach (var line in lines.GetConsumingEnumerable())
        {
            String pattern = "\\s{4,}";

            foreach (String trace in Regex.Split(line, pattern))
            {
                if (trace != String.Empty)
                {
                    String[] details = Regex.Split(trace, "\\s+");

                    Instruction instruction = new Instruction(details[0],
                        int.Parse(details[1]),
                        int.Parse(details[2]));
                    Console.WriteLine("computing...");
                    instructions.Add(instruction);
                }
            }
        }
    });

    // Block until both tasks have completed.
    // This makes this method prone to deadlocking.
    // Consider using 'await Task.WhenAll' instead.
    Task.WaitAll(stage1, stage2);
}

我非常怀疑是你的 CPU 工作阻碍了一切,但如果是这种情况,你也可以像这样并行化第 2 阶段:

    var stage2 = Task.Run(() =>
    {
        var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };

        Parallel.ForEach(lines.GetConsumingEnumerable(), parallelOptions, line =>
        {
            String pattern = "\\s{4,}";

            foreach (String trace in Regex.Split(line, pattern))
            {
                if (trace != String.Empty)
                {
                    String[] details = Regex.Split(trace, "\\s+");

                    Instruction instruction = new Instruction(details[0],
                        int.Parse(details[1]),
                        int.Parse(details[2]));
                    Console.WriteLine("computing...");
                    instructions.Add(instruction);
                }
            }
        });
    });

请注意,如果您的 CPU 工作组件与 IO 组件相比可以忽略不计,您将看不到太多加速。与顺序处理相比,工作负载越均匀,流水线的性能就越好。

由于我们讨论的是性能,请注意,我对上述代码中的阻塞调用数量并不感到特别兴奋。如果我在自己的项目中这样做,我会选择异步/等待路线。在这种情况下,我选择不这样做,因为我想让事情易于理解和集成。

关于c# - 并行读取和处理文件 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20928705/

相关文章:

c# - MS Access 中的日期时间格式

c# - 使用 azure redis 的单元测试和 IDistributedCache

java - 异步for循环没有挂起

编译器: "error: dereferencing pointer to incomplete type" in thread application

C# WinForms ComboBox - 仅从对象中选择值

c# - 将特定数据从 1 个数据表传输到另一个错误

c++ - Eigen 中的多线程(未使用 OpenMP)

c++ - Qt跨线程调用

c# - 如何引用不同的模式而不对其进行硬编码

c - 多线程并行计数器比简单的基于并发锁的计数器慢