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

C# 如果我使用Parallel.ForEach(),为什么会遗漏一些文件?,c#,multithreading,C#,Multithreading,下面是处理大约10000个文件的代码 var files = Directory.GetFiles(directorypath, "*.*", SearchOption.AllDirectories).Where( name => !name.EndsWith(".gif") && !name.EndsWith(".jpg") && !name.EndsWith(".png")).ToList(); Parallel.

下面是处理大约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);
    }

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);
    }
}

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);
    }
}

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

//Parallel.ForEach(files,Countnumberofwordsineachfile);
var fileContent = files
        .AsParallel()
        .Select(f=> f + "=" + Countnumberofwordsineachfile(f));
这需要对计数方法进行更有用的设计:

// make this an 'int' function, more reusable as well
public int Countnumberofwordsineachfile(string filepath)
{ ...; return characterCount; }
但请注意,在这里,并行处理并没有多大帮助,您的主函数(ReadAllText)是I/O绑定的,因此使用
aspallel()
很可能会导致性能下降

更好的选择是使用
目录.EnumerateFiles
,然后在不并行的情况下收集结果:

var files = Directory.EnumerateFiles(....);
var fileContent = files
         //.AsParallel()
         .Select(f=> f + "=" + Countnumberofwordsineachfile(f));

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

//Parallel.ForEach(files,Countnumberofwordsineachfile);
var fileContent = files
        .AsParallel()
        .Select(f=> f + "=" + Countnumberofwordsineachfile(f));
这需要对计数方法进行更有用的设计:

// make this an 'int' function, more reusable as well
public int Countnumberofwordsineachfile(string filepath)
{ ...; return characterCount; }
但请注意,在这里,并行处理并没有多大帮助,您的主函数(ReadAllText)是I/O绑定的,因此使用
aspallel()
很可能会导致性能下降

更好的选择是使用
目录.EnumerateFiles
,然后在不并行的情况下收集结果:

var files = Directory.EnumerateFiles(....);
var fileContent = files
         //.AsParallel()
         .Select(f=> f + "=" + Countnumberofwordsineachfile(f));

你能发布CountNumberOfWordsIneachFile的代码吗?你说的“打印字数”是什么意思?这是一个可以输出10000个数字的控制台应用程序吗?或者你把每个文件的字数加在一起,然后在最后显示出来?你能把Countnumberofwordsineachfile的代码贴出来吗?您是否已检查变量文件是否包含所需的确切数量的文件?是否可以为正在调用的函数添加代码,
Countnumberofwordsineachfile
?什么是
filecontent
?小溪?可能您没有正确处理流,并且流没有完全刷新内容。您可以发布CountNumberOfWordsInEachFile的代码吗?您所说的“打印字数”是什么意思?这是一个可以输出10000个数字的控制台应用程序吗?或者你把每个文件的字数加在一起,然后在最后显示出来?你能把Countnumberofwordsineachfile的代码贴出来吗?您是否已检查变量文件是否包含所需的确切数量的文件?是否可以为正在调用的函数添加代码,
Countnumberofwordsineachfile
?什么是
filecontent
?小溪?可能您没有正确地处理流,并且它没有完全刷新内容。