Все, вот вопрос о дизайне/лучших практиках сложного случая отмены Task: s в C#. Как реализовать отмену общей задачи?Как реализовать отмену совместной задачи: s в C#
В качестве минимального примера допустим следующее: у нас есть долго работающая, совместная операция «Работа». Он принимает маркер отмены в качестве аргумента и выдает, если он был отменен. Он работает в определенном состоянии приложения и возвращает значение. Его результат независимо требуется двумя компонентами пользовательского интерфейса.
Пока состояние приложения не изменяется, значение функции Работы должно быть кэшировано, и если одно вычисление продолжается, новый запрос не должен запускать второй расчет, а скорее начнет ждать результата.
Любой из компонентов пользовательского интерфейса должен иметь возможность отменить свою задачу, не затрагивая задачу других компонентов пользовательского интерфейса.
Вы со мной до сих пор?
Вышеупомянутое может быть выполнено путем ввода кэша задач, который обертывает реальную Рабочую задачу в ресурсах TaskCompletion, чья задача: s затем возвращается компонентам пользовательского интерфейса. Если компонент пользовательского интерфейса отменяет его «Задача», он отменяет задачу TaskCompletionSource, а не основную задачу. Это все хорошо. Компоненты пользовательского интерфейса создают источник CancellationSource, а запрос на отмену - это нормальный дизайн сверху вниз, а внизу - работающий TaskCompletionSource Task.
Теперь, к настоящей проблеме. Что делать, когда изменяется состояние приложения? Предположим, что использование функции «Работа» на копии состояния не представляется возможным.
Одним из решений было бы прослушивание изменения состояния в кеше задач (или там около). Если в кеше есть приложение CancellationToken, используемое основной задачей, тот, который выполняет функцию «Работа», может отменить его. Тогда это может привести к отмене всех подключенных TaskCompletionSources Task: s, и, таким образом, оба компонента пользовательского интерфейса получат отмененные задачи. Это своего рода отказ от снизу вверх.
Есть ли предпочтительный способ сделать это? Существует ли шаблон проектирования, который описывает его где-то?
Снизить снизу можно, но это немного странно. Задача UI создается с помощью CancellationToken, но отменяется из-за другого (внутреннего) CancellationToken. Кроме того, поскольку токены не совпадают, исключение OperationCancelledException нельзя просто игнорировать в пользовательском интерфейсе, что (в конечном итоге) приведет к тому, что исключение будет выбрано во внешнем финализаторе Task: s.
Отличный вопрос, хотя моя первая реакция была "Т.Л., д-р" – dtb
Так, для уточнения; у вас есть два пользователя результата задачи, и вы хотите, чтобы одна задача вычисляла значение для каждого состояния приложения; но вы хотите, чтобы каждый потребитель мог «отменить» ожидание результата задачи? – Tejs
Да, но также и то, что изменение состояния должно отменять вычисление. – 4ZM