views:

140

answers:

0

Hey guys, I just wanted to verify what I'm doing is correct. It came to our attention that a Windows Service had a pretty serious memory leak. I was able to track it down to how Workflow was being called. I reworked it a bit to stop the memory leak, but I wanted to validate that the code is doing what I think it is. Note I do not know the first thing about Workflow, so I'm coming to you.

Basically, the code was executing the Workflow on a thread, but was not removing the handler to WorkflowRuntime.Terminated. I am trying to ensure that the Workflow is executed asynchronously. Here are the relevant portions of code:

Checking to ensure there is only once instance of the WorkflowRuntime:

private static void _CheckRuntimeInstance()
{
     lock (_padlock)
     {
          if (_wfRuntime == null)
          {
               _wfRuntime = new WorkflowRuntime();

               ManualWorkflowSchedulerService schedulerService = new ManualWorkflowSchedulerService();
                _wfRuntime.AddService(schedulerService);
                _wfRuntime.StartRuntime();                 
           }
      }
}

Inside a static method, creating the specific WorkflowInstance to run:

_CheckRuntimeInstance();

// create the instance
WorkflowInstance instance = _wfRuntime.CreateWorkflow(typeof(WorkflowType),parameters);
instance.Start();

Guid instanceId = instance.InstanceId;

ThreadPool.QueueUserWorkItem(CallbackMethod, instanceId);

Thread callback method:

private static void DeviceLocationAssignmentCallback(Object state)
{
     Guid instanceId = (Guid)state;

     EventHandler<WorkflowTerminatedEventArgs> workflowTerminatedHandler = null;
     EventHandler<WorkflowCompletedEventArgs> workflowCompletedHandler = null;

     workflowTerminatedHandler = delegate(object sender, WorkflowTerminatedEventArgs e)
     {
         if (instanceId == e.WorkflowInstance.InstanceId)
         {
             // Remove event registration.
             _wfRuntime.WorkflowTerminated -= workflowTerminatedHandler;
             _wfRuntime.WorkflowCompleted -= workflowCompletedHandler;

             if (e.Exception != null)
             {
                // Log error.
             }
         }
     };

     _wfRuntime.WorkflowTerminated += workflowTerminatedHandler;

     workflowCompletedHandler = delegate(object sender, WorkflowCompletedEventArgs e)
     {
         if (instanceId == e.WorkflowInstance.InstanceId)
         {
             // Remove event registrations.
             _wfRuntime.WorkflowTerminated -= workflowTerminatedHandler;
             _wfRuntime.WorkflowCompleted -= workflowCompletedHandler;
         }
     };

     _wfRuntime.WorkflowCompleted += workflowCompletedHandler;

     _wfRuntime.GetService<ManualWorkflowSchedulerService>().RunWorkflow(instanceId);
}

EDIT: Changed the title of the post to get more views.