c# - 如何填充排序列表的并发字典?

标签 c# concurrency task-parallel-library

假设我有这门课:

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。

最佳答案

更改这部分代码:

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

对此:

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

关于c# - 如何填充排序列表的并发字典?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9410582/

相关文章:

c# - Entity Framework 代码优先 6.0 : is there any annotations to add index to a column(s)

JavaFX:任务不会更新 UI

.net-4.0 - TPL - MaxDegreeOfParallelism 和 MaximumConcurrencyLevel 之间的区别

python - Redis:如何确保购物案例的并发性和原子性?

c# - 如何收听 TPL TaskStarted/TaskCompleted ETW 事件

c# - 如何等待 webclient OpenReadAsync 完成

c# - iTextSharp 打印 gridview

c# - LINQ Skip() 问题

c# - 我如何使用 ffmpeg 修复(组合 1 个音频和 1 个图像)

java - ConcurrentModificationException 尽管使用同步