3

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.

Community
  • 1
  • 1
Dave
  • 14,618
  • 13
  • 91
  • 145
  • 1
    Have you tried unregistering the WorkflowCompleted and WorkflowTerminated events? – overslacked Jan 12 '10 at 19:09
  • you should submit that as an answer. I bet you just hit the nail on the head. I have been using workflow code that is running rampant on the web, yet is flawed in that it uses an approach that prevents unregistration of the event handlers! I'll give that a try now and will mark yours as the answer if you post it here. Thanks for catching that stupid error. – Dave Jan 12 '10 at 19:51
  • This post not only shows a good way to unregister the handlers, but it also showed me how to deal with the other part of my question -- how to differentiate between workflows! http://bit.ly/8pkEWT – Dave Jan 12 '10 at 19:58
  • I guess I jumped to conclusions. I unregistered the event handlers (I set breakpoints to confirm it is happening), and there is *still* a memory leak. Odd. – Dave Jan 12 '10 at 20:23

1 Answers1

2

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
  • 14,618
  • 13
  • 91
  • 145