views:

401

answers:

1

We have used the Factory/Singlton pattern for creating a workflow runtime.

When we run a workflow we use a AutoResetEvent waitHandle.WaitOne() to wait for the workflow to complete.

If two workflows run at the same time they react to the same AutoResetEvent and both calls get the return values that were meant for the first call.

Is there a way to fix this without creating a new workflow runtime for each call?

Thanks

Shiraz

EDIT

Here is a simplified version of the code:

public class Process: IProcess
{
    private AutoResetEvent waitHandle = new AutoResetEvent(false);
    /// <summary>
    /// ReturnValues
    /// </summary>
    private Dictionary<string, object> ReturnValues;

    public ProcessCargo Preprocess(ProcessorCargo cargo)
    {
            try
            {
                WorkflowRuntime workflowRuntime = WorkflowFactory.GetWorkflowRuntime();

                workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowCompleted);
                workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(workflowTerminated);
                workflowRuntime.ServicesExceptionNotHandled += new EventHandler<ServicesExceptionNotHandledEventArgs>(workflowRuntime_ServicesExceptionNotHandled);                    

                Dictionary<string, object> parameters = new Dictionary<string, object>();
                // Add Parameters

                WorkflowInstance workflowInstance;
                workflowInstance = workflowRuntime.CreateWorkflow(typeof(ProcessWorkflow), parameters);
                workflowInstance.Start();

                waitHandle.WaitOne();

                cargo.A = (A)ReturnValues[KeyA];

            }
            catch (Exception e)
            {
                LoggingHelper.LogFault(e);
                throw;
            }
            return cargo;
    }

Here is the workflow factory, it is based on code in the Windows Workflow Foundation Step by Step Book:

public static class WorkflowFactory
{
    // Singleton instance of the workflow runtime
    private static WorkflowRuntime _workflowRuntime = null;

    // Lock (sync) object
    private static object _syncRoot = new object();

    /// <summary>
    /// Factory method
    /// </summary>
    /// <returns></returns>
    public static WorkflowRuntime GetWorkflowRuntime()
    {
        // Lock execution thread in case of multi-threaded
        // (concurrent) access.
        lock (_syncRoot)
        {
            // Check for startup condition
            if (null == _workflowRuntime)
            {
                // Provide for shutdown
                AppDomain.CurrentDomain.ProcessExit += new EventHandler(StopWorkflowRuntime);
                AppDomain.CurrentDomain.DomainUnload += new EventHandler(StopWorkflowRuntime);

                // Not started, so create instance
                _workflowRuntime = new WorkflowRuntime();

                // Start the runtime
                _workflowRuntime.StartRuntime();
            } // if

            // Return singleton instance
            return _workflowRuntime;
        } // lock
    }

    // Shutdown method
    static void StopWorkflowRuntime(object sender, EventArgs e)
    {
        if (_workflowRuntime != null)
        {
            if (_workflowRuntime.IsStarted)
            {
                try
                {
                    // Stop the runtime
                    _workflowRuntime.StopRuntime();
                }
                catch (ObjectDisposedException)
                {
                    // Already disposed of, so ignore...
                } // catch
            } // if
        } // if
    }
}
+1  A: 

A single Windows Workflow runtime can run many workflows at the same time. Its the code you've placed around around the runtime which needs fixing.

What is waiting on the wait handle? Why is waiting? Why are you using the same handle for multiple workflow instances?

AnthonyWJones
Thanks for your answer I have updated my question with a code sample
Shiraz Bhaiji