0

我正在使用此代码TraverseTreeParallelForEach

有时我会神秘地得到聚合异常。Add(T) 处的数组索引越界异常。我将它用于我的备份程序。

public List<string> execute(string filterlist, string[] drives) 
    {
        List<string> returnfiles = new List<string>(); // final list

        foreach (string drive in drives)
        {
            foreach (string filter in filterlist.Split(','))
            {
                TraverseTreeParallelForEach(drive, filter, (f) =>
                {
                    returnfiles.Add(f);
                });
            }
        }

        Console.WriteLine("Returnfiles count " + returnfiles.Count);
        returnfiles.RemoveAll(item => item == null); //remove nulls
        return returnfiles;
    }

Q2。目前搜索 5 个驱动器 ~400GB 需要 1-1.5 分钟,因此任何其他加速搜索或对代码进行任何调整的方法。

Q3。我的程序首先列出然后压缩列表中的文件。生产者-消费者实施能否提高总时间?

4

1 回答 1

0

您对 returnfiles 集合的访问未同步。以下代码确实解决了这个问题。

public List execute(string filterlist, string[] drive) { List returnfiles = new List(); // 最终列表对象 lockObj = new object();

    foreach (string drive in drives)
    {
        foreach (string filter in filterlist.Split(','))
        {
            TraverseTreeParallelForEach(drive, filter, (f) =>
            {
                lock(lockObj)
                {
                   returnfiles.Add(f);
                }
            });
        }
    }

    Console.WriteLine("Returnfiles count " + returnfiles.Count);

// 不需要 returnfiles.RemoveAll(item => item == null); //删除空值返回returnfiles;}

MSDN 示例代码是正确的,但您确实修改了来自多个线程的集合,这将在添加操作期间导致随机错误,因为 List 集合本身不是线程安全的。您可以锁定集合,也可以使用一些线程安全的替代方案。

是的,您可以使用生产者消费者模式来加快速度。例如,您可以使用队列而不是带有锁的列表,并在搜索文件时启动一些任务来压缩文件。这将使您的总备份时间最多增加 1-1.5 分钟,这取决于您备份的数量,这是否值得。

另一件事是,由于您正在从 5 张光盘读取,您可以为每张光盘创建一个队列,这样您就可以最大限度地利用所读取光盘的 IO 带宽。这只有在目标备份设备可以处理增加的 IO 并且您的 SATA 或驱动器连接到的任何总线可以处理磁盘生成的 IO 时才会有所帮助。

于 2013-06-29T05:55:19.747 回答