首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果我使用Parallel.ForEach(),为什么会遗漏一些文件?

如果我使用Parallel.ForEach(),为什么会遗漏一些文件?
EN

Stack Overflow用户
提问于 2013-05-07 16:54:46
回答 2查看 201关注 0票数 1

下面是处理大约10000个文件的代码。

代码语言:javascript
复制
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个文件。有没有人能解释为什么会发生这种情况?

代码语言:javascript
复制
  public void Countnumberofwordsineachfile(string filepath)
    {
        string[] arrwordsinfile = Regex.Split(File.ReadAllText(filepath).Trim(), @"\s+");
        Charactercount = Convert.ToInt32(arrwordsinfile.Length);
        filecontent.AppendLine(filepath + "=" + Charactercount);
    }
EN

回答 2

Stack Overflow用户

发布于 2013-05-07 17:05:10

fileContent可能不是线程安全的。因此,如果两个(或更多)任务试图同时附加到它,其中一个将获胜,另一个将失败。您需要记住要么锁定共享的部分,要么不使用共享数据。

对于您的代码来说,这可能是最简单的解决方案。锁定,同步访问(其他任务必须排队才能访问锁定的部分),所以它会减慢算法的速度,但由于这与计算单词的部分相比非常短,因此这不会是一个大问题。

代码语言:javascript
复制
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);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2013-05-07 17:36:06

原因已经找到了,下面是一个替代实现:

代码语言:javascript
复制
//Parallel.ForEach(files,Countnumberofwordsineachfile);
var fileContent = files
        .AsParallel()
        .Select(f=> f + "=" + Countnumberofwordsineachfile(f));

这就需要对count方法进行更有用的设计:

代码语言:javascript
复制
// make this an 'int' function, more reusable as well
public int Countnumberofwordsineachfile(string filepath)
{ ...; return characterCount; }

但请注意,在这里并行对您没有多大帮助,因为您的主函数(ReadAllText)是I/O受限的,因此您很可能会看到使用AsParallel()的性能下降。

更好的选择是使用Directory.EnumerateFiles,然后在没有并行性的情况下收集结果:

代码语言:javascript
复制
var files = Directory.EnumerateFiles(....);
var fileContent = files
         //.AsParallel()
         .Select(f=> f + "=" + Countnumberofwordsineachfile(f));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16415001

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档