Поругать алгоритм с Task'ами
От: Cynic Россия  
Дата: 12.05.17 23:41
Оценка:
Всем привет. У меня есть два вопроса:
1)
Мне нужен алгоритм с Task'ами который будет выбирать объекты из массива и для каждого объекта в отдельном потоке выполнять некоторые действия. Количество одновременно работающих потоков при этом должно быть ограничено.
Написал такой вариант:
    class TestObject
    {
        public TestObject(string value)
        {
            Value = value;
        }

        public string Value { get; set; }
    }

    class Program
    {
        const int maxTasksCount = 5;
        
        static void Main()
        {
            CancellationTokenSource abortToken = new CancellationTokenSource();

            List<TestObject> testObjects = new List<TestObject>();

            for (int i = 0; i < 20; i++)
            {
                testObjects.Add(new TestObject(i.ToString()));
            }

            var task = Task.Run(() =>
            {
                List<Task> tasks = new List<Task>();

                lock (testObjects)
                {
                    foreach (var obj in testObjects)
                    {
                        if (abortToken.IsCancellationRequested)
                            return;

                        if (tasks.Count >= maxTasksCount)
                        {
                            var index = Task.WaitAny(tasks.ToArray());
                            tasks.RemoveAt(index);
                        }

                        tasks.Add(Task.Run(() => Work(obj, abortToken)));
                    }
                }

                Task.WaitAll(tasks.ToArray());
            });

            task.Wait();

            foreach (var obj in testObjects)
                Console.Write(obj.Value);

            Console.ReadLine();
        }

        static void Work(TestObject obj, CancellationTokenSource abortToken)
        {
            lock (obj)
            {
                Thread.Sleep(1000);

                obj.Value = "!";  // Типа полезная работа

                if (abortToken.IsCancellationRequested)
                    return;
            }
        }
    }

Алгоритм работает, но есть сомнения. Подскажите на сколько правильно я всё сделал и что нужно поправить.
2)
На сколько верно в подобных задачах для приостановки выполнения Task'a использовать ManualResetEvent? Я тут где то вычитал мнение, что Task != Thread и в общем случает один Thread может выполнять несколько Task'ов и один Task может быть размазан по нескольким Thread'ам. На сколько это верно. Под Task'ом я здесь понимаю, элементарный Task без вложенных задач.
:)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.