我有以下代码可以让我执行工作流程。这可以反复调用。经常是。它也存在于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事件中传递了其他对象,所以我看不出它是如何工作的。
......我在这里错过了一些简单的事情,很有可能我的大脑没有告诉我的身体它今天没有出现在工作中。
答案 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
希望这有帮助