Как я могу заполнить параллельный словарь отсортированного списка? - PullRequest
2 голосов
/ 23 февраля 2012

Давайте представим, что у меня есть этот класс:

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.

1 Ответ

2 голосов
/ 23 февраля 2012

Измените эту часть вашего кода:

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

К этому:

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