Как заставить службу рабочего процесса WF4 State Machine выдавать неожиданное имя сообщения?

У меня есть служба рабочего процесса *.xamlx, работающая в IIS, и у меня есть State1, State2 и State3.

Trigger T1 (State 1 -> State 2) listens to "Start" message on Receive Activity.
Trigger T2 (State 2 -> State 3) listens to "Proceed" message on Receive Activity.

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

Как мне получить ожидаемое поведение здесь?

1 ответ

Решение

Я просто вставляю здесь ответ, который получил от Джима Карли - MSFT на форумах MSDN, чтобы он не исчез через несколько лет.

Александр,

Вы сталкиваетесь с ситуацией, когда рабочий процесс имеет как "протокольные закладки", так и "непротокольные закладки". "Закладки протокола" создаются действиями обмена сообщениями (например, получение). "Непротокольные закладки" - это закладки, которые не связаны с операциями обмена сообщениями. А государственная деятельность создает непротокольные закладки внутри страны.

Об этой проблеме сообщалось также при использовании "Pick" - https://social.msdn.microsoft.com/Forums/vstudio/en-US/275f7817-1ec7-433c-89ba-fe48afd1dae8/wf4-wcf-send-message-at-wrong-time?forum=wfprerelease

Вот выдержка из моего объяснения на эту тему:

Основная причина различий в поведении (тайм-аут) при использовании действия Pick или State для инкапсуляции получения для OperationB заключается в том, что действия Pick и State создают внутренние закладки, которые не связаны с закладками, созданными действиями Receive.

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

Представьте себе сценарий, в котором у службы есть "протокол" обмена сообщениями Operation1, за которым следует Operation2:

Receive (Operation1)

SendReply (Operation1)

DoSomeOtherWork

Receive (работы2)

SendReply (работы2)

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

Таким образом, Operation1 может завершиться, а клиент может отправить Operation2 до завершения DoSomeOtherWork. Мы не хотим немедленно отказаться от Операции2. Вместо этого мы вешаем сообщение Operation2 в надежде, что работа, выполняемая DoSomeOtherWork, завершится и закладка, связанная с этой работой, будет возобновлена. После завершения DoSomeOtherWork будет создана закладка протокола для Receive(Operation2), и теперь сообщение от клиента может быть успешно обработано.

Пока DoSomeOtherWork еще не завершен, получено сообщение для Операции 2. Он обнаруживает, что для Operation2 нет закладки протокола. Затем мы проверяем, есть ли какие-либо непротокольные закладки, ожидающие этого экземпляра. Если есть (как в случае, когда DoSomeOtherWork еще не завершен), мы держимся за сообщение. Но если нет других непротокольных закладок, мы немедленно отклоняем сообщение как вышедшее из строя.

Начиная с.NET 4.6, существует набор параметров, который можно указать в файле web.config вашей службы, который управляет обработкой непротокольных закладок и сообщений, вышедших из строя. Чтобы настроить AppSetting, добавьте это в ваш файл web.config:

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

Операция '' на экземпляре службы с идентификатором '' не может быть выполнена в это время. Убедитесь, что операции выполняются в правильном порядке и что используемая привязка обеспечивает заказанные гарантии доставки.

Если значение больше 0, то по истечении указанного времени вы все равно получите исключение тайм-аута.

Опять же, этот новый AppSetting доступен начиная с версии.NET 4.6. И все это предполагает, что BufferedReceive НЕ используется.

Это также задокументировано здесь: http://blogs.msdn.com/b/dotnet/archive/2015/07/20/announcing-net-framework-4-6.aspx?PageIndex=2

Другие вопросы по тегам