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