views:

140

answers:

2

I was writing up a long, detailed question, but just scrapped it in favor of a simpler question that I didn't find an answer to here.

Brief app description:

I have a WPF app that spawns several threads, and each thread executes its own WF. What are some of the best ways to handle errors in the threads and WF that will allow user interaction from the GUI side? I definitely plan to handle any low level exceptions in the thread, because I don't want the thread to exit.

Summary of questions:

  1. How have you implemented communication between WF and the thread that starts it? There is WorkflowTerminated, but I don't want the workflow to exit -- I need to fix the problem and let it continue. I assume the only option is using a FaultHandler, but was wondering if there's another way to do it without using an activity block. I am hoping there's a framework out there that I just haven't found yet.

  2. The error from WF needs to get caught by the thread, which then needs to display the error in the GUI. The user will then make a logical choice for recovery, which should then be sent back to the thread, and then to WF. Again, is there something existing out there that I should take a look at?

Even buzzwords / keywords that accomplish what I am describing would be really helpful, and I can do the legwork on researching each of them. However, any additional insight is always welcome. :)

+1  A: 

What's worked for me in multi-threaded WPF apps is to have the errant thread invoke a callback method that passes the exception and other info back to the UI thread. Callbacks can have return values, so if your thread can block while waiting for the user to respond, then that can work for you. Remember that the callback will run on the thread that calls it, so any UI updates have to be done via the control's dispatcher. You will have to decide whether all of the threads use the same callback and what kind of synchronization you'll need if there's a chance that multiple threads can throw exceptions simultaneously.

ebpower
the thread should definitely block (just itself) while waiting for a user response. I was considering using WaitHandle and AutoResetEvent(s) to make the thread block until the GUI can set the appropriate signal. Is the proper way to create the "I've handled the error" event in the thread, and pass this along to the GUI via a callback? Is there some ".NETish" way to deal with this other than callbacks? I'm certainly comfortable doing it this way, but am also open to other approaches.
Dave
I'm not sure how to define ".NETish way" (which would be a good general question).
ebpower
However, I would lean towards showing each thread's status simultaneously on the UI (perhaps with a listview) so that the user can choose which thread to respond to. Callbacks are my preferred way to signal asynchronously, and are used by a number of .Net libs. Give one a try while you're waiting for a fancier answer.
ebpower
A: 

Here's how I ended up solving this problem. But first a little background info:

User clicks a button in the GUI that causes the candy packager to start running. This is done via a command binding in the ViewModel, which then calls a low-level function in the Model. The function in the model launches a thread and executes a state machine.

At some point, the machine will fail. When it does, I compile information about the error and possible (known) recovery methods. I put this into an object and then pass it to the GUI via a callback interface. In the meantime, the worker thread is stuck waiting for an Event to get set.

Eventually, the candy worker will notice the error and will click a button telling the system what to do. This results in two things: 1) it flags one of the recovery methods as the preferred one, and 2) sets the event. Now the worker thread continues on, checks for the preferred error recovery method and transitions into the respective state in the state machine.

This works very well (so far). The part I know is totally lame is the manner in which it checks for the preferred error recovery method. I am essentially setting a string variable, and then comparing this string to a list of known strings. Ultra lame, but I'm not sure of a better way to do this, other than using an enum. Does anyone have recommendations for me?

Dave