Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 并行循环和读取将在多线程中使用的文件,最佳实践?_C#_Multithreading_Parallel Processing_Readfile - Fatal编程技术网

C# 并行循环和读取将在多线程中使用的文件,最佳实践?

C# 并行循环和读取将在多线程中使用的文件,最佳实践?,c#,multithreading,parallel-processing,readfile,C#,Multithreading,Parallel Processing,Readfile,我正在创建一个应用程序,其中我希望根据xslx文件的内容重命名一堆文件夹中的一堆文件 我正在做一个并行for循环,其中每个文件夹都有自己的“线程”(或whatchamacallit),然后应用程序应该根据文件夹名称,用相应的文件夹名称检索xlsx文件中的所有帖子,并根据从xlsx文件中获得的内容重命名文件夹的内容。我希望这是有道理的 我的问题是:我应该什么时候读取xlsx文件?在我看来,我有两个选择:1)在并行迭代之前打开文件,让每个迭代循环文件的内容以查找文件夹名称。可能的问题是多个线程将同时

我正在创建一个应用程序,其中我希望根据xslx文件的内容重命名一堆文件夹中的一堆文件

我正在做一个并行for循环,其中每个文件夹都有自己的“线程”(或whatchamacallit),然后应用程序应该根据文件夹名称,用相应的文件夹名称检索xlsx文件中的所有帖子,并根据从xlsx文件中获得的内容重命名文件夹的内容。我希望这是有道理的

我的问题是:我应该什么时候读取xlsx文件?在我看来,我有两个选择:1)在并行迭代之前打开文件,让每个迭代循环文件的内容以查找文件夹名称。可能的问题是多个线程将同时检查同一阵列。我不知道那会不会弄虚作假。2) 每次迭代打开一次文件,并循环查找结果。我认为多次打开该文件反而会比必须的要耗费更多的时间

xlsx文件大约有48000行数据

编辑:

我已经放弃了并行for循环,而选择了一个常规的循环,因为有评论和答案建议我这样做,并解释了原因。但我会把它留给其他人去发现


现在的问题是:我应该什么时候打开xlsx文件?(有关详细信息,请参见预编辑)

仅从数据结构中读取数据是安全的,可以同时执行。这不是一个问题。我看到的问题是,如果不对列表执行任何预处理,就会从多个线程中多次扫描列表,这是一种浪费。那么这个呢:

var excelItems = ...; //Fill this in.
var groupedbyFolder = excelItems.GroupBy(x => x.directoryName);
groupedByFolder.AsParallel().ForAll(g => ProcessFolder(g));
这只需遍历数据一次,并且是非常简单的干净代码


您还需要将
aspallel
配置为经验确定的并行度。尝试不同的值。

对于I/O绑定操作,不应使用多线程。即使您使用真正快速的存储设备,如SSD或RAID,也不会从多线程中获得太多性能提升。对于普通硬盘,性能实际上会变得更差。例如,尝试复制多个文件或同时提取多个zip存档。您会很快注意到性能下降,这是由于多个线程不断地争夺单个I/O设备。

我运行了一些测试,以了解您可能会获得何种性能改进(如果有的话)。我决定创建10000个文件,并使用
秒表
,计算重命名文件所需的时间。我使用了单线程和多线程的方法

代码如下:

//var path = @"D:\Users\Enigmativity\Temporary\SOTest"; //HDD
var path = @"C:\_temporary\SOTest"; //SSD
var files = 10000;
var format = "00000";

var rnd = new Random();
Enumerable
    .Range(0, files)
    .OrderBy(n => rnd.NextDouble())
    .ForEach(n => File.WriteAllText(System.IO.Path.Combine(path, n.ToString(format) + ".txt"), n.ToString()));
然后我运行了以下命令:

var sw = Stopwatch.StartNew();
Enumerable
    .Range(0, files)
    .ToList()
    .ForEach(n =>
        System.IO.File.Move(
            System.IO.Path.Combine(path, n.ToString(format) + ".txt"),
            System.IO.Path.Combine(path, n.ToString(format) + n.ToString(format) + ".txt")));
sw.Stop();
并将其与此进行比较:

var sw = Stopwatch.StartNew();
Enumerable
    .Range(0, files)
    .GroupBy(x => 10 * x / files)
    .AsParallel()
    .ForAll(ns =>
        ns
            .ToList()
            .ForEach(n =>
                System.IO.File.Move(
                    System.IO.Path.Combine(path, n.ToString(format) + ".txt"),
                    System.IO.Path.Combine(path, n.ToString(format) + n.ToString(format) + ".txt"))));
sw.Stop();
每次运行结束时,我都会清理文件:

Directory.EnumerateFiles(path).ForEach(x => File.Delete(x));
我的结果是:

Single thread on HDD: 2,155 milliseconds
Multi-threads on HDD: 1,601 milliseconds

Single thread on SSD: 2,457 milliseconds
Multi-threads on SSD: 940 milliseconds

我多次运行这些结果,每次运行的时间大致相同。SSD并行运行给我带来了巨大的好处,而HDD带来了中等的好处。

所有文件夹都在同一个物理磁盘上吗?是的。没错。那么,你确定为每个文件夹启动一个并行线程是值得的吗?很可能你要在磁盘IO上等待很多时间……CPU处理硬盘驱动器活动的相对速度相差几个数量级。通过使用多个线程,实际工作每1秒可以节省1毫秒。这不值得。事实上,同时访问磁盘会导致大量的寻道时间,实际上会使您的程序慢得多。实际上我不确定。作为一名程序员,我自学成才,所以我并没有真正掌握所有的基础知识,我的知识充其量只是零散的。我一直在学习一些东西,因为任何特定的工作项目都需要一些东西。那么“等待磁盘io”是什么意思呢?我想说我得到了这个答案,但我没有。完全(自学程序员)xlsx文件已按文件夹名称分组。如果这是你要求的一部分。我从你的回答中得出的结论是,也许我应该循环遍历xlsx文件,而不是文件夹数组,然后检查是否要处理该特定文件夹,然后再进行处理?这将只是一个线程,我需要这是一个快速的操作。虽然重命名通常是。但您希望一次处理一个文件夹,对吗?(“每个文件夹都有自己的“线程”)。您应该在一组文件夹上运行某种形式的并行循环。这是这个答案的最后一行。如何生成这组文件夹并不重要。我在这里举了一个例子,我认为你的数据看起来像什么,但显然我猜错了。关于并行加速,不同的硬件有不同的并行性。甚至磁盘也可以从中受益,因为文件系统层具有并行性,一个物理IO可以重命名多个文件(有时)。如果按物理位置排序,磁盘访问也会变得更加高效。SSD具有真正的硬件并行性。你的更新说你已经放弃了并行性,如果你没有测量它,这是一个错误。另一个答案通常是不正确的,它假设了非常有利的条件来进行推理。所以我应该使用并行迭代?这可能是一个加号。它很容易实现,所以您可能应该这样做并测量不同的DOP,包括1.Aha!我明白了!谢谢你的提示,实际上我从来没有想过这个。我基本上认为多线程=总是更快。@Christopherén,作为一个经验法则:mulithreading=更快的计算(CPU限制的操作)。有一些例外,ofc。你可以用不同的DOP进行实验。第三方物流所选择的通常是愚蠢的,也不适合IO。并行度。