C# 用C语言并行处理文件#

C# 用C语言并行处理文件#,c#,multithreading,parallel-processing,plinq,C#,Multithreading,Parallel Processing,Plinq,我有一个代码,它读取文件中的所有单词,为每个唯一的单词分配ID,并将其添加到字典中。我需要使它并行运行以提高应用程序的效率。我尝试过使用Parallel.ForEach而不是ForEach但是,使用lock向字典中添加新词和ID并不能提高效率。。。你们能告诉我并行化代码的最好方法吗 //static object locker = new object(); string[] fnames; // Files are collected from a save file dial

我有一个代码,它读取文件中的所有单词,为每个唯一的单词分配ID,并将其添加到字典中。我需要使它并行运行以提高应用程序的效率。我尝试过使用
Parallel.ForEach
而不是
ForEach
但是,使用lock向字典中添加新词和ID并不能提高效率。。。你们能告诉我并行化代码的最好方法吗

    //static object locker = new object();
    string[] fnames; // Files are collected from a save file dialog
    Dictionary<string, IndexEntry> ID = new Dictionary<string, IndexEntry>(); 
    foreach (var fname in fnames)
        {

            string[] lines = File.ReadAllLines(fname);
            for (int i = 0; i < lines.Length; i++)
            {
                string[] Raw = Regex.Split(lines[i], @"\W+");

                for (int j = 0; j < Raw.Length; j++)
                {
                    string z = Raw[j];

                    if (!ID.ContainsKey(z))
                    {
                        ID.Add(z, new IndexEntry());
                    }
                }
//静态对象锁定器=新对象();
字符串[]fnames;//从“保存文件”对话框中收集文件
字典ID=新字典();
foreach(fnames中的变量fname)
{
string[]lines=File.ReadAllLines(fname);
对于(int i=0;i< /代码> 如果该代码块是由多个线程访问的,ID首先考虑一个并发的字典,它是线程安全的。这将为您实现锁定。

编辑:


生产者/消费者模式是您的朋友

您可以让一个线程读取文件,第二个线程插入字典,可能还有第三个线程执行任何需要执行的处理。只有当字典在开始处理之前不必完全填充时(例如,如果足够读取给定行),第三个线程才适用

请注意,如果处理步骤很简单,那么与单线程解决方案相比,您的收益将很小

查看。它非常适合这种类型的处理


我使用这种模式来读取、处理和写入(到DB)相当大(1GB+)的XML文档。

问题是,您最大的时间消耗者是读取文件:

string[] lines = File.ReadAllLines(fname);
你一下子就把它搞定了。每个文件可能都有一个线程,但我认为这不会给你带来多大好处,因为它们的I/O都在争夺同一个磁盘。试着把它分成更小的部分。类似这样的操作可能会对你有帮助:

static Dictionary<string,IndexEntry> ProcessFiles( IEnumerable<string> filenames )
{
  IEnumerable<string> words = filenames
                              .AsParallel()
                            //.WithMergeOptions( ParallelMergeOptions.NotBuffered )
                              .Select( x => ReadWordsFromFile(x) )
                              .SelectMany( x => x )
                              ;

  Dictionary<string,IndexEntry> index = new Dictionary<string,IndexEntry>() ;
  foreach( string word in words ) // would making this parallel speed things up? dunno.
  {
    bool found = index.ContainsKey(word) ;
    if ( !found )
    {
      index.Add( word, new IndexEntry() ) ;
    }
  }
  return index ;
}

static Regex rxWord = new Regex( @"\w+" ) ;
private static IEnumerable<string> ReadWordsFromFile( string fn )
{
  using( StreamReader sr = File.OpenText( fn ) )
  {
    string line ;
    while ( (line=sr.ReadLine()) != null )
    {
      for ( Match m = rxWord.Match(line) ; m.Success ; m = m.NextMatch() )
      {
        yield return m.Value ;
      }
    }
  }
}
静态字典处理文件(IEnumerable文件名)
{
IEnumerable words=文件名
.天冬酰胺()
//.WithMergeOptions(ParallelMergeOptions.NotBuffered)
.Select(x=>ReadWordsFromFile(x))
.SelectMany(x=>x)
;
字典索引=新字典();
foreach(单词中的字符串)//这样做会加快速度吗?不知道。
{
bool found=index.ContainsKey(word);
如果(!找到)
{
Add(word,newindexentry());
}
}
收益指数;
}
静态正则表达式rxWord=新正则表达式(@“\w+”);
私有静态IEnumerable ReadWordsFromFile(字符串fn)
{
使用(StreamReader sr=File.OpenText(fn))
{
弦线;
而((line=sr.ReadLine())!=null)
{
for(匹配m=rxWord.Match(行);m.Success;m=m.NextMatch())
{
收益率&收益率m值;
}
}
}
}

只有在每次循环迭代中都有大量计算时,并行化才会有所帮助,而这里的情况看起来并非如此。因此,与其告诉我们您提出的解决方案并询问我们如何使其工作,不如告诉我们更多关于您的实际问题,我们可以提出一个可行的解决方案odeReview stack exchange网站更适合这类问题,但只要快速浏览一下它,它看起来像是您按单词分割文件行,就有一个
string.split
方法,我相信它比
Regex.split
快得多(无论如何)使用ConcurrentDictionary将消除锁定词典的需要。这个问题似乎离题了,因为它更适合Thx!我将深入了解更多信息