Проблема / методы PLINQ для реализации многопоточных списков без блокировки - PullRequest
0 голосов
/ 21 августа 2009

Вот код, о котором идет речь:

             parentNodes.AsParallel().ForAll(parent =>
            {
                List<Piece> plist = parent.Field.GetValidOrientations(pieceQueue[parent.Level]);

                plist.ForEach(p =>
                {
                    TreeNode child = new TreeNode(p, parent);
                    var score = child.CalculateScore(root);
                    levelNodes.Add(child);
                });

            });

Во время выполнения этот код иногда оставляет нулевые ссылки в узлах уровня. Я подозреваю, что это связано с блокировкой потока, потому что проблема исчезает, если вместо ForAll вызывается обычный (не параллельный) ForEach.

С имплементацией PLINQ, 'levelNodes.Add (child);' также иногда выдает исключение IndexOutOfRangeException с сообщением: «Исходный массив был недостаточно длинным. Проверьте srcIndex и длину, а также нижние границы массива.»

Есть предложения по устранению этой проблемы?
Или, возможно, производительность будет увеличена с помощью импликации List без блокировок? (Как можно поступить об этом?)

1 Ответ

4 голосов
/ 21 августа 2009

Вам действительно нужны оба уровня параллелизма здесь? Разве не достаточно просто распараллелить родительские узлы?

В любом случае, запись в List<T> из нескольких потоков без блокировки, если определенно не является хорошей идеей. Тем не менее, PFX поставляется с параллельной коллекцией, которая может соответствовать вашим потребностям: ConcurrentBag. Он неупорядочен (чтобы он был свободен от блокировки), но, учитывая взаимодействие между потоками, я думаю, это не проблема для вас.

...