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