Search code examples
workflow-foundation-4

How should I handle exceptions in an AsyncCodeActivity?


I'm experiencing problems with an exception not caught in my workflows. I have a custom AsyncCodeActivity surrounded by a TryCatch; anyway, the exception is not caught and, worse, my IIS pool hosting the workflow is sometimes restarted. Looking at this question/answer (Exception escapes from workflow despite TryCatch activity), I'm thinking that the problem is in the way I rethrow exceptions. This is how I usually write async code activities:

    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        Action<object> execute = s => this.Execute();
        var task = new Task(execute, state, CancellationToken.None, TaskCreationOptions.PreferFairness);
        task.ContinueWith(s => callback(s));
        task.Start();
        return task;
    }

    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        var task = result as Task;
        Contract.Assert(task != null);
        if (task.IsFaulted && task.Exception != null)
        {
            Contract.Assert(
                task.Exception.InnerException != null,
                "It is expected that the inner exception in a task is not null");
            const string Message = "An exception was thrown while doing something";
            Logger.ErrorException(Message, task.Exception.InnerException);
            throw new WorkflowApplicationException(Message, task.Exception.InnerException);
        }
    }

    private void Execute()
    {
         // Do something here
    }

Is it the correct way to handle exceptions in async code activities? if yes, how should I prevent my workflow from aborting (and sometimes restarting IIS)? Thanks


Solution

  • I don't think WorkflowApplicationException was meant to be thrown by your code. I wouldn't be surprised if somewhere we are treating this exception differently and not invoking the TryCatch block because this exception (and it's subclasses) are typically thrown by the workflow runtime and there wouldn't be a point of catching them in an activity if the runtime is hosed.

    You could try throwing a different exception to see if that makes a difference.