views:

283

answers:

1

Here's a overview of my workflow implementation:

  • GUI thread starts worker thread
  • worker thread analyzes some data
  • worker thread starts several other worker threads to work on subsets of data
  • each of these last worker threads creates a workflow runtime and executes a sequential workflow

Up until now, I've been creating a new WorkflowRuntime object in each thread like this:

  using( WorkflowRuntime workflow_runtime = new WorkflowRuntime()) {
      AutoResetEvent waitHandle = new AutoResetEvent(false);
      workflow_runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
      workflow_runtime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
      {
          Console.WriteLine(e.Exception.Message);
          waitHandle.Set();
      };

      WorkflowInstance instance = workflow_runtime.CreateWorkflow(typeof(MyWorkflow), parameters);
      instance.Start();
      waitHandle.WaitOne();
}

The reason for doing it this way is that I need to know when a specific workflow instance has been terminated or errored. The problem is that it causes a huge memory leak in my application, as mentioned here on SO.

If I use the using keyword, or even if I call Dispose and set the workflow_runtime reference to null, I get a massive memory leak. However, if I implement the workflow runtime as a Singleton, as described in this post, memory usage is very low and consistent. I can see when workflows are launched and completed by blips in the graph.

The problem is, if I use the Singleton pattern for the WF runtime, how will I know when a specific workflow has an error? If I just register the event handlers, won't all of them get called when any of the workflows get terminated or completed?

EDIT: should I just use another handle on the stack for errors, and then wait for either to be set, and then check which one was set? I should have considered that before.

+1  A: 

So here is how I have decided to solve the problem. If there is something wrong with my solution, please post comments and I will mark someone else's answer instead, if it's correct.

I changed the code to unregister the event handlers in my previous post, and confirmed that the code was executing by setting breakpoints. After running the application, it still leaked 1.5GB.

One of my issues with the Singleton pattern is that I didn't know how to handle different instances of the workflows. It turns out that I just had to check the InstanceID of the Instance passed through the event args and make sure they matched. This is how you deal with disparate workflow events.

I implemented the Singleton pattern from http://bit.ly/8pkEWT and in addition, unregistered the event handlers and handled the InstanceIDs. The memory leak is gone! However, I haven't gotten around to validating the results of each workflow. (yikes)

Dave