以下是处理大约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);
}
答案 0 :(得分:4)
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);
}
}
答案 1 :(得分:1)
原因已经找到,这是另一种实现方式:
//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));