Подтвердить что ты не робот

Блокировка ресурсов с помощью async/wait

У меня есть приложение, в котором у меня есть общий ресурс (система движения), к которому могут обращаться несколько клиентов. У меня есть отдельные Операции, которые требуют доступа к системе в течение всего хода, и которые должны бросать "Занятые" исключения, если в то же время запрашиваются конфликтующие операции. У меня также есть Секвенсоры, которым необходимо получить эксклюзивный доступ к системе Motion для выполнения нескольких Операций, перемежающихся с другими действиями; в течение всей последовательности никакие другие клиенты не смогут запускать Операции.

Я традиционно обращался к этому, используя Thread-affinity, так что Thread может запрашивать эксклюзивный доступ и выполнять блокирующие вызовы, соответствующие операциям. Хотя Thread имеет доступ, никакие другие Threads не могут использовать ресурс. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что я перешел к внедрению моей системы с использованием шаблонов async/await, чтобы обеспечить реализацию более чистого секвенсора. Проблема в том, что теперь мой секвенсор не всегда работает в одном потоке; активный поток может меняться в ходе обратных вызовов, поэтому уже нелегко определить, действительно ли я в допустимом контексте, чтобы продолжать выполнять операции. Один из примечаний состоит в том, что некоторые из самих Операций состоят из ожиданий, что означает, что обе последовательности и отдельные операции могут охватывать несколько потоков.

Мой вопрос: знает ли кто-нибудь хороший шаблон для получения эксклюзивного доступа при наличии переключения потоков из-за асинхронного/ожидающего?

Для справки, несколько вещей, которые я рассмотрел:

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

  • Создайте доступный токен доступа, чтобы перейти к методам операции, чтобы доказать, что вы получили доступ. Это имеет недостаток в раздувании методов с помощью параметра токена.

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

4b9b3361

Ответ 1

Мой вопрос: знает ли кто-нибудь хороший шаблон для получения эксклюзивного доступа при наличии переключения потоков из-за асинхронного/ожидающего?

Да, вы можете использовать AsyncLock, который также доступен как часть моего Библиотека AsyncEx. Если вы хотите иметь операцию "TryLock", вам может понадобиться создать свой собственный примитив.

Вы потеряете часть возможности выполнять проверки безопасности: нет способа проверить, имеет ли текущий исполняемый поток конкретный AsyncLock.

Другие варианты включают ConcurrentExclusiveSchedulerPair (который я размещаю здесь здесь) или поток данных TPL.