Вот несколько параметров на разных этапах выполнения, которые вы можете использовать для обработки исключений.
Первый вариант (во время выполнения операции / рабочего процесса):
Прежде всего, при пользовательских действиях вы всегда должны пытаться обрабатывать исключения внутри их выполнения. Некоторые действия могут не работать, но общий рабочий процесс может продолжаться и, в таких случаях, регистрировать ошибку на постоянство и даже показывать пользователю, что что-то работает не так, как ожидалось, но вещь продолжится - хорошие варианты.
При этом всегда будут случаи, когда действие должно (и даже должно) генерировать исключения, и они должны обрабатываться на уровне рабочего процесса. Что-то вроде: если это исключение возникает в этом действии, сделайте это, в противном случае сделайте это .
Предположим, у вас есть пользовательское действие, которое что-то сохраняет в БД:
public sealed PersistIntegerToDb : CodeActivity
{
public InArgument<int> ValueToPersist { get; set; }
protected override void Execute(CodeActivityMetadata metadata)
{
try
{
// persist
}
catch(SqlException exception)
{
// re throws the SqlException
throw new SqlException("'ValueToPersist' wasn't persisted.", exception);
}
}
}
Затем в вашем коде или в конструкторе вы можете выполнить действие TryCatch , чтобы отловить эту ошибку и обработать ее так, как вы хотите:
var workflow = new TryCatch
{
Try = new PersistIntegerToDb
{
ValueToPersist = 10
},
Catches =
{
new Catch<SqlException>
{
Action = new ActivityAction<SqlException>
{
Handler = new WriteLine
{
Text = "An error occurred and the value wasn't saved! Anyway workflow will continue..."
}
}
}
}
}
Или вы можете прекратить его, используя TerminateWorkflow .
Второй вариант (во время разработки):
Хорошо, но вы можете утверждать, что клиент не знает, что он должен обрабатывать эти случаи . В этом случае, и это вариант удобства использования, который вы могли бы рассмотреть, вместо того, чтобы делать доступным PersistIntegerToDb
в конструкторе, вы можете предоставить действие, уже окруженное обработчиками исключений, для обработки, через IActivityTemplateFactory :
public sealed PersistIntegerToDbFactory : IActivityTemplateFactory
{
public Activity Create(DependencyObject target)
{
return new TryCatch
{
Try = new PersistIntegerToDb
{
ValueToPersist = 10
},
Catches =
{
new Catch<SqlException>
{
}
}
};
}
}
Теперь вы просто добавляете PersistIntegerToDbFactory
, как если бы это было обычное действие:
new ToolboxItemWrapper(typeof(PersistIntegerToDbFactory), null, "Persist Integer");
Третий вариант (во время проверки):
Никогда не забывайте проверить рабочий процесс перед выполнением!
var validationResults =
ActivityValidationServices.Validate(workflow);
foreach(var error in validationResults.Errors)
{
Console.WriteLine(string.Format(
"Validation error '{0}', generated on activity '{1}' in the property named {2}",
error.Message,
error.Source.DisplayName,
error.PropertyName));
}
Четвертый вариант (во время выполнения приложения):
Вы можете обработать все необработанные исключения, которые могут произойти во время выполнения, используя событие OnUnhandledException:
var wfApp = new WorkflowApplication(activity);
wfApp.OnUnhandledException +=
delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
if (e.UnhandledException is SqlException)
{
Console.WriteLine("Some data wasn't properly persited.");
}
else
{
Console.WriteLine("Unknown error: " + e.UnhandledException.GetType());
Console.WriteLine("With message: " + e.UnhandledException.Message);
}
Console.WriteLine("Ok, workflow will be abort");
return UnhandledExceptionAction.Abort;
};
Обратите внимание, что на этом этапе вы можете только прервать, отменить и прекратить рабочий процесс, и по этой причине вам следует 1) избегать создания исключений или 2) обрабатывать исключения в вашем рабочем процессе. OnUnhandledException
- это ваш последний шанс элегантно завершить выполнение рабочего процесса, и его всегда следует рассматривать, даже если для целей ведения журнала. Может произойти что-то вроде DivideByZeroExceptions , и его практически невозможно предсказать и отловить, например, во время проверки.