2013-08-20 3 views
0

Приложение, которое я разрабатываю, составлено таким образом: Задача производителя сканировать файловую систему для текстовых файлов и помещать ссылку на них в мешок. Многие потребительские задачи принимают файлы refs из сумки одновременно и читают файлы (и делают короткую работу с их содержимым)Концепция «сумка задач» в C#, enqueue, пауза, отмена логических задач

Я должен быть в состоянии приостановить и возобновить весь процесс.

Я пробовал использовать TPL, создавая задачу для каждого файла ref, поскольку они помещаются в сумке (в этом случае сумка - это всего лишь концепция, производитель непосредственно создает потребительскую задачу при поиске файлов), но это Я не могу контролировать задачу, которую я создаю, я не могу (или я не знаю, как это сделать) их приостанавливать. Я могу написать некоторый код, чтобы приостановить поток, выполняющий в настоящее время задачу, но это разрушит точку работы с логическими задачами вместо manully создания потоков, не так ли? Я хотел бы, чтобы что-то вроде «задачи, уже назначенные на физическую нить, могут завершиться, но ожидание логических задач не должно начинаться до команды«

Как я могу добиться этого? Можно ли это сделать с помощью TPL или использовать другое?

EDIT: Ваши ответы действительны, но мое основное сомнение остается без ответа. Мы говорим о задачах, если я использую TPL, мой продюсер, и мой многопользователь будет задачами (правильно?), А не потоками (ну, нормально в момент выполнения задач будет отображаться по потокам). Каждый найденный механизм синхронизации (например, предложенный в комментарии «ManualResetEventSlim») работает на уровне потоков.

E.g. описание метода Wait() для «ManualResetEventSlim» означает «Блокирует текущий поток до тех пор, пока не будет установлен текущий ManualResetEventSlim».

Мое знание задачи чисто академическое, я не знаю, как все работает в «реальном мире», но мне кажется логичным, что мне нужен способ координации (wait/signal/...) задач в уровень задачи или вещи могут стать странными ... например ... две задачи могут быть сопоставлены в одном и том же потоке, но один должен был сигнализировать о другом, ожидающем затем тупике. Я немного смущен. Вот почему я спросил, может ли мое приложение использовать TPL вместо простых стилей старого стиля.

+1

Да, вам придется создать механизм паузы самостоятельно. Использование, например, «ManualResetEventSlim», которые потребители многократно ждут, и что производитель устанавливает/сбрасывает для приостановки/возобновления. – Alex

+0

Обычная 'Task' всегда выполняется в одном потоке. Поэтому любой примитив синхронизации, который работает на 'Thread', также работает с' Task'. – svick

+0

@svick Что делать, если я запускаю 100 задач, которые выполняют тот же код, содержащий Wait()? основанный на принятом ответе на этот вопрос http://stackoverflow.com/questions/14515207/whats-the-proper-way-to-use-a-threadpool 100 ожидающий поток будет создан, это хорошо? – flagg19

ответ

1

Да, вы можете это сделать. Во-первых, у вас есть основной поток, ваше приложение. Там у вас есть два рабочих, представленных потоками. Первым рабочим будет продюсер, а второй рабочий будет потребителем.

Когда ваше приложение начинается, вы начинаете работу. Оба они работают на коллекции параллелизма, сумке. Продюсер ищет файлы и помещает ссылки на сумку, а потребитель берет ссылки из сумки и запускает задание для справки.

Если вы хотите сигнализировать паузу, просто приостановите работу производителя. Если вы это сделаете, потребитель также перестанет работать, если в сумке ничего нет. Если это не является желательным поведением, вы можете просто определить, что приостановка продюсера также очищает сумку - сначала создайте резервную сумку и очистите ее. Таким образом, все запущенные задачи завершат работу, и потребитель не будет запускать новые задачи, но он все равно может работать и ждать результатов.

EDIT:

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

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

+0

Это не тот ответ, который я искал, но спасибо за идею очистка/резервное копирование пакета. – flagg19

+0

Да, с моей точки зрения, это лучшее решение. Если вы отправляете уведомление, чтобы приостановить приложение, очистите сумку и попросите свой потребительский поток сделать паузу, используя Thread.Sleep, если в сумке ничего нет. Но зависит от ваших требований. Благодаря параллелизму на месте есть множество решений, которые вы можете попытаться оптимизировать для своего приложения. –

0

Уверенный, что вы можете использовать TPL для этого. И может быть также reactive extensions и LINQ для упрощения группировки и pausing/resuming работает нить.

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

Я представляю себе что-то вроде этого:

  • Вы сканер каталога нити помещает найденные файлы в наблюдаемые коллекции.
  • Потребительский поток подписывает изменения коллекции и получает/удаляет файлы и назначает их работникам.
Смежные вопросы