下面是处理大约10000个文件的代码。
var files = Directory.GetFiles(directorypath, "*.*", SearchOption.AllDirectories).Where(
name => !name.EndsWith(".gif") && !name.EndsWith(".jpg") && !name.EndsWith(".png")).ToList();
Parallel.ForEach(files,Countnumberofwordsineachfile);Countnumberofwordsineachfile函数将每个文件中的字数打印到文本中。每当我实现Parallel.ForEach()时,我每次在处理的时候都会丢失大约4-5个文件。有没有人能解释为什么会发生这种情况?
public void Countnumberofwordsineachfile(string filepath)
{
string[] arrwordsinfile = Regex.Split(File.ReadAllText(filepath).Trim(), @"\s+");
Charactercount = Convert.ToInt32(arrwordsinfile.Length);
filecontent.AppendLine(filepath + "=" + Charactercount);
}发布于 2013-05-07 17:05:10
fileContent可能不是线程安全的。因此,如果两个(或更多)任务试图同时附加到它,其中一个将获胜,另一个将失败。您需要记住要么锁定共享的部分,要么不使用共享数据。
对于您的代码来说,这可能是最简单的解决方案。锁定,同步访问(其他任务必须排队才能访问锁定的部分),所以它会减慢算法的速度,但由于这与计算单词的部分相比非常短,因此这不会是一个大问题。
private object myLock = new object();
public void Countnumberofwordsineachfile(string filepath)
{
string[] arrwordsinfile = Regex.Split(File.ReadAllText(filepath).Trim(), @"\s+");
Charactercount = Convert.ToInt32(arrwordsinfile.Length);
lock(myLock)
{
filecontent.AppendLine(filepath + "=" + Charactercount);
}
}发布于 2013-05-07 17:36:06
原因已经找到了,下面是一个替代实现:
//Parallel.ForEach(files,Countnumberofwordsineachfile);
var fileContent = files
.AsParallel()
.Select(f=> f + "=" + Countnumberofwordsineachfile(f));这就需要对count方法进行更有用的设计:
// make this an 'int' function, more reusable as well
public int Countnumberofwordsineachfile(string filepath)
{ ...; return characterCount; }但请注意,在这里并行对您没有多大帮助,因为您的主函数(ReadAllText)是I/O受限的,因此您很可能会看到使用AsParallel()的性能下降。
更好的选择是使用Directory.EnumerateFiles,然后在没有并行性的情况下收集结果:
var files = Directory.EnumerateFiles(....);
var fileContent = files
//.AsParallel()
.Select(f=> f + "=" + Countnumberofwordsineachfile(f));https://stackoverflow.com/questions/16415001
复制相似问题