У меня есть рабочий процесс внутри службы Windows, который представляет собой цикл, который периодически выполняет работу. Работа выполняется в рамках действия TryCatch
. Свойство Try
является действием TransactionScope
, которое охватывает некоторые пользовательские действия, которые читают и обновляют базу данных. Когда транзакция завершится неудачно, я ожидаю, что любое исключение, вызвавшее это, будет обнаружено TryCatch
. Тем не менее, мой рабочий процесс прерывается. Рабочий процесс у меня следующий:
var wf = new While(true)
{
Body = new Sequence
{
Activities =
{
new TryCatch
{
Try = new TransactionScope
{
IsolationLevel = IsolationLevel.ReadCommitted,
Body = new Sequence
{
Activities = { ..custom database activities.. }
},
AbortInstanceOnTransactionFailure = false
},
Catches =
{
new Catch<Exception>
{
Action = new ActivityAction<Exception>
{
Argument = exception,
Handler = ..log error..
}
}
}
},
new Delay { Duration = new InArgument<TimeSpan>(duration) }
}
},
}
В моем случае, возможно, база данных иногда недоступна, поэтому очевидно, что транзакция не будет зафиксирована. В этом случае происходит следующее: рабочий процесс прерывается со следующим исключением:
System.OperationCanceledException: ошибка обработки текущего рабочего элемента привела к прерыванию рабочего процесса.
Внутреннее исключение:
System.Transactions.TransactionException: операция недопустима для состояния транзакции.
Это имеет смысл, потому что я только что выключил базу данных. Однако, почему это исключение не обрабатывается моей TryCatch
активностью?
EDIT 1 : некоторая дополнительная информация. Я запускаю рабочий процесс, используя класс WorkflowApplication
. Чтобы лучше понять, что происходит, я указал свойства Aborted
и OnUnhandledException
. Когда возникает исключение, оно переходит непосредственно к Aborted
, а OnUnhandledException
пропускается (хотя это явно необработанное исключение).
РЕДАКТИРОВАТЬ 2 : я включил журнал отладки, и это дает некоторую дополнительную информацию. «Пользовательские действия с базой данных» успешно завершены. Первая запись в журнале событий, указывающая, что что-то не так, - это подробное сообщение уровня: Транзакция времени выполнения завершила с состоянием «Прервано» . Затем я вижу информационное сообщение: WorkflowInstance Id: 'dbd1ba5c-2d8a-428c-970d-21215d7e06d9' E2E Activity (не уверен, что это значит). И информационное сообщение после этого: Действие 'System.Activities.Statements.TransactionScope', DisplayName: «Транзакция для запуска немедленно проверяет», InstanceId: «389» завершено в состоянии «Ошибка» .
После этого сообщения я вижу, что каждый родитель (включая действие TryCatch
) завершает работу в состоянии «Сбой», заканчивая прерыванием моего рабочего процесса.
РЕДАКТИРОВАТЬ 3 : Для ясности, все работает, как и ожидалось, когда возникает исключение в любой из «пользовательских операций с базой данных». Обнаружено исключение, и рабочий процесс продолжается. Это происходит только тогда, когда транзакция не может быть зафиксирована в конце TransactionScope
. Смотрите следующую трассировку стека, которая регистрируется из обратного вызова Aborted
:
at System.Transactions.TransactionStateInDoubt.Rollback(InternalTransaction tx, Exception e)
at System.Transactions.Transaction.Rollback(Exception e)
at System.Activities.Runtime.ActivityExecutor.CompleteTransactionWorkItem.HandleException(Exception exception)
Если вы будете следовать вызовам из TransactionScope.OnCompletion(...)
, в итоге вы получите класс ActivityExecutor
из стековой трассировки.