2012-02-23 43 views
2

让我们想象一下我有这个类:如何填充排序列表的并发字典?

public class FileData 
{ 
    public Weigth { get; set; } // Not the file size, but a business weight 
    public Name { get; set; } // Name of the file 
    public FullPath { get; set; } // full path of the file 
} 

我想探索一堆单独的文件夹中,从不同的网络位置。这个想法是,能够,给定一个特定的文件名,检索所有的候选文件,按照文件的重量排序。

我想分开探索每个文件夹在一个单独的线程。在这种情况下,我的“商店”应该是并发访问感知。

我试过使用ConcurrentDictionary<string, SortedSet<CdlFileInfo>>类来存储探索结果。

但是,我有点挣扎着填充内部排序集的正确方法。

我已经试过这样:

class Program 
{ 
    private readonly static ConcurrentDictionary<string, SortedSet<CdlFileInfo>> g_Files = new ConcurrentDictionary<string,SortedSet<CdlFileInfo>>(); 
    public static void Main() 
    { 
     PopulateFileList(); 

     // Do something with the list of files 
    } 
    private static void PopulateFileList() 
    { 
     var sources = AnyMethodToGetFoldersList(); // IEnumarable<string> 
     sources.AsParallel().ForAll(x => 
     { 
      Console.WriteLine("Enumerating files in {0}", x.Folder); 
      var allFiles = Directory.GetFiles(x.Folder, "*.*", SearchOption.AllDirectories); 

      foreach (var file in allFiles) 
      { 
       var fd = new FileData { 
        Weigth = GetWeigth(file), // returns a int... the method is not important 
        Name = Path.GetFileName(file), 
        FullPath = file 
       }; 

          // Here is the key piece of my code 

       g_Files.AddOrUpdate(
        fileName, 
        new SortedSet<FileData>() { fd }, 
        (filePath, source) => 
        { 
         g_Files[fileName].Add(fd); 
         return g_Files[fileName]; 
        } 
       ); 
      } 
     }); 
    } 

    public class FileData 
    { 
     public Weigth { get; set; } // Not the file size, but a business weight 
     public Name { get; set; } // Name of the file 
     public FullPath { get; set; } // full path of the file 
    } 
    public class FileDataWeightComparer : IComparer<CdlFileInfo> 
    { 
     public int Compare(FileData x, FileData y) 
     { 
      return Comparer<int>.Default.Compare(x.Weigth,y.Weigth); 
     } 
    } 
} 

此代码 “似乎” 工作。这是正确的方式吗?此代码在访问现有的SortedSet时是否阻止线程问题?

此代码似乎不起作用。我可以看到一些找到的值丢失了。我怀疑AddOrUpdate方法的最后一个参数不能正确锁定内部SortedSet。

回答

2

更改您的这部分代码:

(filePath, source) => 
{ 
    g_Files[fileName].Add(fd); 
    return g_Files[fileName]; 
} 

要这样:

(filePath,source) => 
{ 
    source.Add(fd); 
    return source; 
} 
+0

确定。这解决了我一半的问题。其实,使用'SortedSet '会引起副作用。由于我使用的是自定义比较器,因此该设置只能为每个重量值保留一个值。在我的情况下,几个项目可以具有相同的重量。我用一个简单的列表取代了这个集合,它可以工作(不需要锁定,因为外部的ConcurrentDictionary为我管理锁定。 – 2012-02-23 11:23:17