Постоянство рабочего процесса и закладки как переключение рабочего процесса
У меня есть набор пользовательских действий, которые используются в сложных рабочих процессах.
Я хотел бы сделать их (настраиваемые действия) постоянными, не имея рабочего процесса в состоянии ожидания. Это должна быть система аварийного переключения, поэтому, когда что-то идет не так во время выполнения рабочего процесса, это может быть:
- приостановлено пользователем (в любое время) и позже возобновлено из закладки / точки, в которой она была приостановлена (например, пользователь заметил, что внешняя система не работает, и он хочет приостановить рабочий процесс на время).
- в случае необработанного исключения мы можем возобновить выполнение с последней закладки / момента времени
- остановка узла WorkflowApplication может произойти в любое время, и мы можем возобновить выполнение с последней закладки / момента времени
Я работал в течение нескольких дней с постоянным рабочим процессом, но я не уверен, смогу ли я достичь своей цели с его помощью. Зачем?
- Я мог бы использовать блокировку закладок в каждом настраиваемом упражнении, но блокирование рабочего процесса и перезапуск его только с целью сохранения его не выглядит многообещающим.
- Я мог использовать неблокирующие закладки, но не смог увидеть их в базе данных и возобновить с нее.
Можете ли вы посоветовать мне, это закладки рабочего процесса, путь сюда?
Я вижу свет в неблокирующих закладках, но не могу их сохранить и возобновить позже. Не могли бы вы дать мне несколько советов, как сохранить неблокирующую закладку для последующего возобновления?
Редактировать:
В wf3 был атрибут PersistOnClose
что было бы достаточно для моего требования. в wf4 его заменили на Persist
деятельность, которая также может быть полезной, однако я не хочу иметь дополнительные действия в моих и без того сложных рабочих процессах.
В идеале было бы здорово иметь возможность выполнить context.RequestPersist(callback)
от NativeActivityContext
, однако этот метод является внутренним (и все, что находится внутри него, не видно снаружи оригинальной сборки.
2 ответа
Вот что я пришел с:
- Неблокирующие закладки не являются опцией. Хотя неблокирующая закладка не препятствует завершению создания, но также не приводит к тому, что экземпляр рабочего процесса становится бездействующим - это означает, что он не будет сохранен. Неблокирующие закладки отбрасываются после завершения действия (которое его создало). Эта закладка может быть возобновлена, только если создание действия еще не завершено.
- С помощью
PersistOnCloseAttribute
это не вариант, потому что я использую WF4 и этот атрибут только.NET 3.x WF. - Блокирующие закладки не могут быть использованы, потому что они блокируют выполнение рабочего процесса, что нежелательно.
Решение заключается в использовании Persist
активность в каждой сделанной на заказ деятельности (должна расширяться NativeActivity
который может запланировать деятельность ребенка):
//class field
Activity childActivity = new Persist();
Чтобы это работало, его нужно добавить в метаданные как ImplmentationChild:
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddImplementationChild(this.childActivity);
}
Последнее, что нужно сделать, - запланировать дочернюю активность из метода Execute (не имеет значения, где сохранение будет происходить только после завершения вызывающей операции *).
protected override void Execute(NativeActivityContext context)
{
//...
context.ScheduleActivity((Activity)this.childActivity);
}
Чтобы сохранить рабочий процесс после необработанного исключения, этот фрагмент кода должен быть добавлен в WorkflowApplication:
application.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
return UnhandledExceptionAction.Abort;
};
* возврат из Execute
Метод не обязательно означает, что действие "завершено" - т.е. внутри действия есть блокировка закладок (см. недостатки ниже).
Есть несколько недостатков этого решения:
- Решение сохраняет только одно состояние рабочего процесса (последнее состояние).
- Упорство может произойти только после завершения деятельности. Это означает, что постоянное / возобновление не может быть сделано с середины действия.
- Он не работает с параллельными циклами / последовательностями - действия из параллельного цикла / последовательности сохраняются после завершения всего параллельного процесса. Он работает правильно с обычными циклами / последовательностями.
- Блокирующие закладки имеют огромное влияние на это решение (если они создаются при создании действия или в других дочерних действиях по созданию действия). Они приводят к тому, что действие не завершается, даже если возвращен метод Execute. В конце концов, Persist выполнится (либо после завершения действия, либо до перехода в состояние ожидания).
Если я правильно понимаю ваш вопрос, то у вас есть требования ниже.
- Постоянство и восстановление рабочего процесса.
- Пользователь может приостановить и возобновить.
- В случае каких-либо исключений рабочий процесс сохраняется и возобновляется со следующего действия.
Вы можете подойти, используя следующие шаги.
- Вы можете использовать сервис WF + WCF для выполнения и размещения вашего рабочего процесса.
- Добавьте постоянство и отслеживание с базой данных, такой как сервер Sql, если вы используете oracle, то можете использовать Devart.
- Настройте ControlEnpont для приостановки и возобновления.
- Мудро используйте try/ Catch и сохраняемость для обработки исключений.
в случае возникновения каких-либо проблем и настройки требуется обсудить то же самое.:) так как я разработал рабочий процесс, похожий на ваш.