Многопоточность в .Net - PullRequest
       19

Многопоточность в .Net

2 голосов
/ 19 апреля 2011

У меня есть xml конфигурации, который используется пакетным модулем в моем приложении Windows .Net 3.5. Каждый узел в xml сопоставлен с классом .Net. Каждый класс выполняет обработку, как математические вычисления, выполняет вызовы БД и т. Д.

Пакетный модуль загружает XML, идентифицирует класс, связанный с каждым узлом, а затем обрабатывает его.

Теперь у нас есть следующие требования:

1. Предположим, есть 3 класса [3 узла в xml] ... A, B и C. Класс A может зависеть от класса B ... т.е. нам нужно выполнить класс B перед обработкой класса A. Обработка класса C должна выполняться в отдельном потоке.

2. Если поток запущен, тогда мы сможем отменить этот поток в середине его обработки.

Нам нужно реализовать весь этот модуль, используя многопоточность .net.

Мои вопросы: 1. Можно ли выполнить вышеуказанное требование № 1? Если да, то как?

2. Учитывая эти требования, является ли .Net 3.5 хорошей идеей или .Net 4.0 был бы лучшим выбором? Хотите узнать о преимуществах и недостатках, пожалуйста.

Спасибо за чтение.

Ответы [ 3 ]

4 голосов
/ 19 апреля 2011

Было бы лучше использовать Task Parallel Library (TPL) в .NET 4.0 .Это даст вам множество полезных функций для абстрагирования от реального процесса создания потоков в пуле потоков.Вы можете использовать шаблон параллельных задач для создания Задачи для каждого из заданий, определенных в XML, и TPL будет обрабатывать планирование этих задач независимо от оборудования.Другими словами, если вы перейдете на компьютер с большим количеством ядер, TPL будет планировать больше потоков.

1) TPL поддерживает понятие задач продолжения .Вы можете использовать их для обеспечения порядка задач и передачи результата одной Задачи или будущего от антецедента к продолжению.Это фьючерсный паттерн .

        // The antecedent task. Can also be created with Task.Factory.StartNew.
        Task<DayOfWeek> taskA = new Task<DayOfWeek>(() => DateTime.Today.DayOfWeek);

        // The continuation. Its delegate takes the antecedent task
        // as an argument and can return a different type.
        Task<string> continuation = taskA.ContinueWith((antecedent) =>
            {
                return String.Format("Today is {0}.",
                                    antecedent.Result);
            });

        // Start the antecedent.
        taskA.Start();

        // Use the contuation's result.
        Console.WriteLine(continuation.Result);

2) Отмена потока поддерживается TPL, но это совместное аннулирование .Другими словами, код, выполняемый в Задаче, должен периодически проверять, отменено ли оно, и корректно ли закрываться.TPL имеет хорошую поддержку для отмены .Обратите внимание, что если вы будете использовать потоки напрямую, вы столкнетесь с теми же ограничениями.Thread.Abort не является жизнеспособным решением почти во всех случаях.

Пока вы это делаете, вы можете захотеть взглянуть на контейнер внедрения зависимостей , такой как Unity, для генерации сконфигурированных объектов из вашего XMLконфигурация.

Ответ на комментарий (ниже)

Джимми: Я не уверен, что понимаю комментарий Холтавольта.Что верно, так это то, что использование параллелизма окупается только в том случае, если объем работы делается значительным, в противном случае ваша программа может потратить больше времени на управление параллелизмом, выполняющим полезную работу.Фактические наборы данных не должны быть большими, но работа должна быть значительной.

Например, если ваши входные данные были большими числами, а вы проверяли, являются ли они простыми, набор данных будет очень маленьким, но параллелизм все равно окупится, потому что вычисления являются дорогостоящими для каждого числа или блока чисел.И наоборот, у вас может быть очень большой набор данных, который вы искали для четности.Это потребовало бы очень большого набора данных, но вычисления все еще очень дешевы, и параллельная реализация могла бы все еще быть не более эффективной.

Канонический пример использует Parallel.For вместо for для перебора набора данных (большого или маленького), но только для выполнения простой числовой операции, такой как сложение.В этом случае ожидаемое улучшение производительности при использовании нескольких ядер перевешивается накладными расходами на создание параллельных задач, планирование и управление ими.

1 голос
/ 19 апреля 2011

Конечно, это можно сделать.

Предполагая, что вы новичок, я, скорее всего, рассмотрю многопоточность, и вы захотите 1 поток на класс, а затем я посмотрю на класс backgroundworker и в основном использую его в разных классах для обработки .

Какая версия .NET вы хотите использовать, также зависит от того, будет ли она работать и на клиентских машинах. Но я бы пошел на .NET 4 просто потому, что он самый новый, и если вы хотите разделить одну задачу на несколько потоков, для этого есть встроенные классы.

0 голосов
/ 19 апреля 2011

Учитывая ваш вариант использования, должно быть достаточно Thread и BackgroundWorkerThread .Читая информацию MSDN, касающуюся этих классов, вы обнаружите, что вы захотите поддерживать отмену как средство завершения работающего потока до его завершения.(Поток «убивать» - это то, чего следует избегать, если это вообще возможно)

.NET 4.0 добавил некоторые дополнительные элементы в библиотеку параллельных задач (TPL) - где задачи определяются и управляются с некоторой более умной привязкой кпоследнее использовавшееся ядро ​​(для обеспечения лучшего поведения кэша и т. д.), однако это выглядит излишним для вашего варианта использования, если только вы не собираетесь использовать очень большие наборы данных.Смотрите эти сайты для получения дополнительной информации:

http://msdn.microsoft.com/en-us/library/dd460717.aspx

http://archive.msdn.microsoft.com/ParExtSamples

...