TraverseTreeParallelForEach MSDN示例异常

时间:2013-06-29 04:53:04

标签: c#

我正在使用此代码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。我的程序首先列出&amp;然后压缩列表中的文件。生产者 - 消费者实施能否改善总时间?

1 个答案:

答案 0 :(得分:0)

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

public list execute(string filterlist,string [] drives)     {         列表returnfiles = new List(); //最终名单         object 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 =&gt; item == null); //删除空值         return returnfiles;     }

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

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

另一件事是,由于您正在阅读5张光盘,因此您可以为每张光盘创建一个队列,这样您就可以最大限度地提取您从中读取的光盘的IO带宽。这仅在目标备份设备可以处理增加的IO并且如果您的SATA或连接驱动器的任何总线可以处理光盘生成的IO时有用。