Параллельно. Для сбоя (C #) - PullRequest
4 голосов
/ 18 июня 2011

Я написал некоторый код:

class Program
    {
        public const int count = 3000;
        static List<int> list = new List<int>();
        static void DoWork(int i)
        {            
            list.Add(i);
        }        
        static void Main(string[] args)
        {
            while (true)
            {

                Stopwatch s = new Stopwatch();
                s.Start();
                Parallel.For(0, count + 1, DoWork);            
                s.Stop();
                Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString());
                Console.WriteLine("Expected: {0}", count + 1);
                Console.WriteLine("count: {0}", list.Count);
                Console.ReadKey();
                list = new List<int>(); 
            }
        }
    }

, но результаты не ожидаются (

Не все циклы завершены до вызова Console.WriteLine

Что такоепроблема с использованием Parallel.For?

Ответы [ 3 ]

7 голосов
/ 20 июня 2011

Вы сталкиваетесь с так называемым условием гонки .Поскольку коллекция List в .Net не является поточно-ориентированной, такие операции, как Add(), не являются атомарными.По сути, вызов Add () в одном потоке может уничтожить Add () другого потока до его завершения.Для вашего кода вам нужна потокобезопасная параллельная коллекция.

Попробуйте:

using System.Threading.Tasks;
class Program
{

    public const int count = 3000;
    static ConcurrentBag<int> bag = new ConcurrentBag<int>();
    static void DoWork(int i)
    {
        bag.Add(i);
    }
    static void Main(string[] args)
    {
        while (true)
        {

            Stopwatch s = new Stopwatch();
            s.Start();
            Parallel.For(0, count + 1, DoWork);
            s.Stop();
            Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString());
            Console.WriteLine("Expected: {0}", count + 1);
            Console.WriteLine("count: {0}", bag.Count);
            Console.ReadKey();
            bag = new ConcurrentBag<int>();
        }
    }
}

ConcurrentBag - это самая близкая вещь к потокобезопасному списку.Только помните, поскольку мы имеем дело с неизвестным планированием, целые числа не будут в порядке.

1 голос
/ 18 июня 2011

List<T> не является потокобезопасным классом.Вместо этого вам следует использовать одну из коллекций Concurrent или реализовать собственную синхронизацию.

Подробнее о Parallel.For

см. этот ответ
1 голос
/ 18 июня 2011

Класс List<> не сохраняет потоки.Вы не можете изменить его в параллельном цикле (без проблем).Используйте форму коллекции System.Collections.Concurrent пространство имен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...