1

The following is newly created thread code that has been successfully started by my UI thread (the UI code is not here).

When I single step in debugging I do get to this code.

When the workflow that I am executing does not have any problems, the code runs to completion. But when the workflow is faulty (I am testing my code by using a faulty workflow) this code does not catch the WorkflowException that happens during the wf.Run() statement below.

I think I have the workflow execution exception handling code below?? Can you tell me what I am doing wrong? Thanks.

public void ThreadRun ()
    {  
            AutoResetEvent syncEvent = new AutoResetEvent(false);
            var wf = ActivityXamlServices.Load(fileInfo.FileName);
            // Create the WorkflowApplication using the desired
            // workflow definition.
            WorkflowApplication wfApp = new WorkflowApplication(wf);

            // Handle the desired lifecycle events.
            wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
            {
                syncEvent.Set();
            };

            try
            {
                // Start the workflow.
                wfApp.Run();
                // Wait for Completed to arrive and signal that
                // the workflow is complete.
                syncEvent.WaitOne();
            }
            catch (Exception exception)
            {

                wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
                {
                    if (e.CompletionState == ActivityInstanceState.Faulted)
                    {
                        Console.WriteLine("Workflow {0} Terminated.", e.InstanceId);
                        Console.WriteLine("Exception: {0}\n{1}",
                            e.TerminationException.GetType().FullName,
                            e.TerminationException.Message);
                    }
                    else if (e.CompletionState == ActivityInstanceState.Canceled)
                    {
                        Console.WriteLine("Workflow {0} Canceled.", e.InstanceId);
                    }
                    else
                    {
                        Console.WriteLine("Workflow {0} Completed.", e.InstanceId);

                        // Outputs can be retrieved from the Outputs dictionary,
                        // keyed by argument name.
                        // Console.WriteLine("The winner is {0}.", e.Outputs["Winner"]);
                    }
                };

                wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
                {
                    // Display the exception that caused the workflow
                    // to abort.
                    Console.WriteLine("Workflow {0} Aborted.", e.InstanceId);
                    Console.WriteLine("Exception: {0}\n{1}",
                        e.Reason.GetType().FullName,
                        e.Reason.Message);
                };

                wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
                {
                    // Perform any processing that should occur
                    // when a workflow goes idle. If the workflow can persist,
                    // both Idle and PersistableIdle are called in that order.
                    Console.WriteLine("Workflow {0} Idle.", e.InstanceId);
                };

                wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
                {
                    // Instruct the runtime to persist and unload the workflow.
                    // Choices are None, Persist, and Unload.
                    return PersistableIdleAction.Unload;
                };

                wfApp.Unloaded = delegate(WorkflowApplicationEventArgs e)
                {
                    Console.WriteLine("Workflow {0} Unloaded.", e.InstanceId);
                };

                wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
                {
                    // Display the unhandled exception.
                    Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
                        e.InstanceId, e.UnhandledException.Message);

                    Console.WriteLine("ExceptionSource: {0} - {1}",
                        e.ExceptionSource.DisplayName, e.ExceptionSourceInstanceId);

                    // Instruct the runtime to terminate the workflow.
                    // Other choices are Abort and Cancel. Terminate
                    // is the default if no OnUnhandledException handler
                    // is present.
                    return UnhandledExceptionAction.Terminate;
                };
            }
        }
Steve Czetty
  • 6,147
  • 9
  • 39
  • 48
user1298925
  • 2,304
  • 7
  • 29
  • 43
  • why do you set the delegates after you catch the exception, by the way?... – Qnan Aug 17 '12 at 17:01
  • I have also tried setting the delegates before the try {wfApp.Run()) – user1298925 Aug 17 '12 at 17:59
  • as well. I guess my question is about the structure of the code in the following case. Thread A starts thread B. And thread B executes workflow> Where and how do I catch the workflow issues ?In thread A or Thread B. Also, how do I do that. In summary my question is about the sturcture, and where shoudl I put the delegate code. I am an experienced programmer in C++ but new to all these. Thanks. – user1298925 Aug 17 '12 at 18:01
  • It's sufficient to set a callback for OnUnhandledException before you run the wfApp. Whenever there is an unhandled exception, this callback will be invoked. Check http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.onunhandledexception.aspx – Qnan Aug 17 '12 at 18:05
  • delegate is pretty much like a pointer to a method in C++, if that makes things clearer. – Qnan Aug 17 '12 at 18:06
  • The answer to your question "and what result did you get?" is I get a InvaliddWorkflowException was unhandled!!!! Although I follwoed your advice and I put all the delegate code before wfApp.run() including the wfApp.OnUnhandledException delegate. – user1298925 Aug 17 '12 at 18:27
  • one exclamation mark is generally sufficient – Qnan Aug 17 '12 at 20:40
  • It seems to me that the exception is caught just fine in this scenario, I've just reproduced it. The fact is logged in the Console, whatever code you have in the `catch` is executed and the program execution continues. Also, I would like to point out that you assign to different delegates to wfApp.Completed, which is probably not necessary. – Qnan Aug 17 '12 at 20:55

2 Answers2

3

That's cause the exception is thrown in a different thread, I think. Check this: catch exception that is thrown in different thread

The exceptions thrown in a different thread are not passed to the caller thread by default.

EDIT: I have the impression that you would like the delegates to be set before the workflow starts, is that correct? If so, do the assignments to wfApp.OnUnhandledException and such before you do the wfApp.Run().

Community
  • 1
  • 1
Qnan
  • 3,714
  • 18
  • 15
  • Thanks. Are you saying the following code belongs to the UI thread? : wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e) ETC.. – user1298925 Aug 17 '12 at 17:07
  • yes. it's setting a callback, so the code inside the delegate will not be executed in the UI. That is basically just telling the wfApp "in case there's an `UnhandledException`, do this and that" – Qnan Aug 17 '12 at 17:10
  • 1) I had to set the delegates before wfApp.Run() – user1298925 Aug 20 '12 at 20:11
  • 2)The setting of the delegates had to be done in the second thread which I believe is not considered the UI thread , so it is the other thread (whatever the terminlogy calls it?). 3) And in case of an exception I can only catch it in the catch statement after the "try" in which I put a MessageBox.Show. SUMMARY: I still dont know why the code for unexpected exception never gets hit although I execute a faulty workflow. The catch statement gets executed but NOT the delegate code for unhandled exception. When I execute a error-free workflow the delegate code for Completed gets executed. – user1298925 Aug 20 '12 at 20:29
  • @user1298925 apparently there is a difference between an exception within the workflow and an InvaliddWorkflowException, which is somehow external, as it is not thrown by anything *inside* the workflow. Try adding a Throw activity to your workflow, like in the example here http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.onunhandledexception.aspx, and you will have OnUnhandledException invoked. – Qnan Aug 20 '12 at 22:43
0

I think you just have to handle the OnUnhandledException event before the catch (i see you have this event handled but in your catch block).

wfApp.OnUnhandledException will let you catch the error.