提高Windows Workflow的速度

时间:2010-09-23 21:19:08

标签: c# .net-3.5 workflow-foundation

我有以下代码可以让我执行工作流程。这可以反复调用。经常是。它也存在于web服务中,因此可能同时有多个调用它。这目前有效。但它很慢,因为每次实例化WorkflowRuntime非常慢。

我该如何改善这个?

public class ApprovalWorkflowRunner : IApprovalWorkflowRunner
{
    private static ILogger Logger { get; set; }
    private static IRepository Repository { get; set; }

    public ApprovalWorkflowRunner(ILogger logger, IRepository repository)
    {
        Logger = logger;
        Repository = repository;
    }

    public Request Execute(Action action)
    {
        var request = new Request();

        using (var workflowRuntime = new WorkflowRuntime())
        {
            workflowRuntime.StartRuntime();
            var waitHandle = new AutoResetEvent(false);
            workflowRuntime.WorkflowCompleted += ((sender, e) =>
                                                    {
                                                        waitHandle.Set();
                                                        request = e.OutputParameters["gRequest"] as Request;
                                                    });
            workflowRuntime.WorkflowTerminated += ((sender, e) =>
                                                    {
                                                        waitHandle.Set();
                                                        Logger.LogError(e.Exception, true, action.Serialize());
                                                    });

            var parameters = new Dictionary<string, object>
                                {
                                    {"RepositoryInstance", Repository},
                                    {"RequestID", action.RequestID.ToString()},
                                    {"ActionCode", action.ToString()}
                                };

            var instance = workflowRuntime.CreateWorkflow(typeof (ApprovalFlow), parameters);
            instance.Start();
            waitHandle.WaitOne();
        }

        return request;
    }
}

理想情况下,我想保留一份WorkflowRuntime。但是因为我在CreateWorkflow函数和WorkflowCompleted事件中传递了其他对象,所以我看不出它是如何工作的。

......我在这里错过了一些简单的事情,很有可能我的大脑没有告诉我的身体它今天没有出现在工作中。

2 个答案:

答案 0 :(得分:0)

一个运行时可以同时运行多个工作流。根据答案:

该页面显示了我将在下面包含的WorkflowRuntime工厂的一些代码,我认为这些代码最初取自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
    }
}

你只需致电

WorkflowFactory.GetWorkflowRuntime();

编辑: 好的,对不起。您可以尝试检查实例是您期望的实例,如果不是,则返回实例。请注意,此代码未经测试,只是试图了解这个想法。

public class ApprovalWorkflowRunner : IApprovalWorkflowRunner
{
    private static ILogger Logger { get; set; }
    private static IRepository Repository { get; set; }

    public ApprovalWorkflowRunner(ILogger logger, IRepository repository)
    {
        Logger = logger;
        Repository = repository;
    }

    public Request Execute(Action action)
    {
        var request = new Request();

        var workflowRuntime = WorkflowFactory.GetWorkflowRuntime();

        workflowRuntime.StartRuntime();
        var waitHandle = new AutoResetEvent(false);
        WorkflowInstance instance = null;
        workflowRuntime.WorkflowCompleted += ((sender, e) =>
                                                {
                                                    if (e.WorkflowInstance != instance) return;
                                                    waitHandle.Set();
                                                    request = e.OutputParameters["gRequest"] as Request;
                                                });
        workflowRuntime.WorkflowTerminated += ((sender, e) =>
                                                {
                                                    if (e.WorkflowInstance != instance) return;
                                                    waitHandle.Set();
                                                    Logger.LogError(e.Exception, true, action.Serialize());
                                                });

        var parameters = new Dictionary<string, object>
                            {
                                {"RepositoryInstance", Repository},
                                {"RequestID", action.RequestID.ToString()},
                                {"ActionCode", action.ToString()}
                            };

        instance = workflowRuntime.CreateWorkflow(typeof (ApprovalFlow), parameters);
        instance.Start();
        waitHandle.WaitOne();

        return request;
    }
}

答案 1 :(得分:0)

我会对您目前使用的代码做一些观察。在做任何优化代码的事情时,你应该牢记一下目标何时你的代码足够有效,因为代码优化往往遵循递减收益的规律,因为代码优化需要越来越多的努力。

我能想到的提高代码速度最简单的方法是将WorkflowRuntime实例中的ValidateOnCreate属性设置为false。默认情况下,它设置为true,这意味着每次创建工作流实例时。我假设您的工作流是静态的,因为您没有在运行时对其进行动态更改,而是在编译时对其进行了定义。如果是这种情况,您应该可以跳过验证步骤。根据您的工作流程的复杂程度,这可能会显着提高代码的速度。

假设这不足以提高速度,其他建议如下。使ApprovalWorkflowRunner类的Execute方法实例成员中使用的WaitHandle,Request和Workflow对象成为可能。 WorkflowRuntime将是Execute方法的参数。在执行此操作时,您应该每次要运行ApprovalFlow工作流时创建ApprovalWorkflowRunner类的新实例。你的Execute方法应该是这样的:

    public Request Execute(Action action, WorkflowRuntime workflowRuntime) {
            workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
            workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(workflowRuntime_WorkflowTerminated);

            var parameters = new Dictionary<string, object>
                        {
                            {"RepositoryInstance", Repository},
                            {"RequestID", action.RequestID.ToString()},
                            {"ActionCode", action.ToString()}
                        };

            mWorkflowInstance = workflowRuntime.CreateWorkflow(typeof(ApprovalFlow), parameters);
            mWorkflowInstance.Start();
            mWaitHandle.WaitOne();

        return mRequest;
    }

ApprovalWorkflowRunner类中的事件处理程序如下所示:

    void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e) {
        if (!e.WorkflowInstance.Equals(mWorkflowInstance)) return;
        mRequest = e.OutputParameters["gRequest"] as Request;
        mWaitHandle.Set();
        return;
    }

请注意,我已经将处理程序中的两行切换为您在代码中使用它们的方式,在之前设置等待句柄,您分配请求实例会创建竞争条件。

最后一点:在WorkflowRuntime实例上调用Dispose方法显然必须在代码的其他地方进行;但Microsoft建议在调用Dispose之前调用StopRuntime方法:Remarks: shut down the WorkflowRuntime gracefully

希望这有帮助