Реализация «только один из» и «не в параллельной семантике с задачей параллельной библиотеки»

StackOverflow https://stackoverflow.com/questions/3613812

  •  26-09-2019
  •  | 
  •  

Вопрос

Какой был бы лучший подход для выполнения задач с ключом, который работает следующим образом: -

Вариант 1) только один из этого ключа когда-либо ожидается. Может использоваться, например, из ASP.NET MVC для очереди одного визуализации для миниатюрного изображения независимо от того, сколько раз URL-адрес изображения. Только один бежит, все остальные запросы ждут этого для завершения.

Вариант 2) Все элементы с одним и тем же ключом должны выполняться последовательно. Может использоваться, например, для обеспечения того, чтобы операции, которые извлекают файл из подложки в локальный кэш, не все пытаются получить файл в кеш одновременно. Вариант 1 - это особый случай этого, где последующие действия с одним и тем же ключом просто отбрасываются (обычно сохраняются только проверки файлов).

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

Вложенные задачи с продолжениями выглядят обнадеживающими, но поддерживая словарь в настоящее время задачи Queue'D вскоре становится грязным между TaskFactory и классами задач. Наследование от задачи также проблематично, поскольку ни CaseFactoryory, ни задачcheduler не являются общими для задачи.

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

Кто-нибудь реализовал что-нибудь подобное этому, используя TPL, и если да, какой подход вы предприняли в своей задаче, задачахCheduler и CassFactory Classe?

Это было полезно?

Решение

Возможно, один из способов того, что я могу думать, это

  1. Создайте класс обертки - скажите KeyProcessor для очереди вверх элементы для ключа.
  2. Способ keyProcessor.run () будет способен на любую семантику в очереди, для которой вам нужны. По сути, это будет искать внутреннюю очередь для любой ожидающей работы, а затем продолжать выполнять его последовательно.
  3. Поддерживать словарь ключевые объекты к ключевымпроцессором.
  4. Для любой новой задачи, проверьте в словаре для того же ключа. Если не существует, то добавьте его. Очередь задача на нем. Если он не работает, затем запланируйте его с помощью метода запуска в качестве действия.
  5. Используйте ContinualWith, чтобы расписание сопровождающего задания - например, всякий раз, когда задача выполняет keyProcessor.run, задачи продолжения могут проверить, есть ли дополнительные задачи запланированы для одного и того же ключа (поскольку он завершен) и запускает его снова или удалить из словаря.

Все вышеперечисленное было бы сложно от точка синхронизации потоков не для нескольких интересных коллекций, присутствующих в System.Collions.concurrent пространство имен. Это сделало бы вышесказанную логику гораздо более проще. Например, Concurrentdictionary.getoradd. позволит поиску и / или добавить объект ключейпроцессора в безопасном порядке.

Другие советы

Эта проблема похожа на одну, я решил в Реактивный экземпляр, Хотя мой также не вомечал предыдущие запросы. Посмотрите на код для Queuedasyncmrucache. (и это запись в блоге) - Этот код сочетает в себе TPL с реактивными расширениями, чтобы получить этот вид вещей, но он делает важную гарантию, что 2-й запрос на тот же ключ блокирует первый запрос в полете, вместо того, чтобы выдать еще один.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top