using MainShell.Common; using MainShell.ProcessResult; using MW.WorkFlow; using Stylet; using System; using System.Linq; using System.Threading.Tasks; namespace MainShell.Process { public class WorkflowRunCompletedEventArgs : EventArgs { public WorkflowState FinalState { get; } public string Error { get; } public string FailureMessage { get; } public MessageKey FailureMessageKey { get; } public object[] FailureMessageArguments { get; } public WorkflowRunCompletedEventArgs(WorkflowState finalState, string error, string failureMessage, MessageKey failureMessageKey, object[] failureMessageArguments) { FinalState = finalState; Error = error; FailureMessage = failureMessage; FailureMessageKey = failureMessageKey; FailureMessageArguments = failureMessageArguments ?? Array.Empty(); } } /// /// 封装工作流的启动、停止和状态管理,用于手动流程的复用。 /// public class WorkflowRunner : PropertyChangedBase, IDisposable { private WorkflowEngine _workflowEngine; private bool _isRunning; /// /// 流程是否正在运行 /// public bool IsRunning { get { return _isRunning; } private set { SetAndNotify(ref _isRunning, value); } } public event EventHandler RunCompleted; /// /// 运行单个 Activity(自动包装为单步工作流) /// public Task RunActivityAsync(IActivity activity, WorkflowContext context) { if (activity == null) throw new ArgumentNullException(nameof(activity)); // 自动构建单步工作流定义 var stepId = "SingleStep_" + Guid.NewGuid().ToString("N"); var step = new WorkflowStep(stepId, activity); var definition = new WorkflowDefinition(stepId); definition.AddStep(step); return RunAsync(definition, context); } public Task RunActivityWithResultAsync(IActivity activity, WorkflowContext context) { if (activity == null) throw new ArgumentNullException(nameof(activity)); var stepId = "SingleStep_" + Guid.NewGuid().ToString("N"); var step = new WorkflowStep(stepId, activity); var definition = new WorkflowDefinition(stepId); definition.AddStep(step); return RunWithResultAsync(definition, context, null); } /// /// 运行完整的工作流定义 /// public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context) { await RunWithResultAsync(definition, context, null); } public Task RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context) { return RunWithResultAsync(definition, context, null); } /// /// 运行完整的工作流定义,并支持从指定步骤启动。 /// /// 工作流定义 /// 工作流上下文 /// 可选:指定起始步骤ID;为 null/空时从初始步骤启动 public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId) { await RunWithResultAsync(definition, context, startStepId); } public async Task RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId) { if (definition == null) throw new ArgumentNullException(nameof(definition)); if (context == null) throw new ArgumentNullException(nameof(context)); if (IsRunning) { throw new InvalidOperationException("当前已有流程正在运行,无法重复启动。"); } if (!string.IsNullOrWhiteSpace(startStepId) && !definition.GetAllStepIds().Contains(startStepId)) { throw new ArgumentException($"指定的起始步骤ID '{startStepId}' 不存在于工作流定义中。", nameof(startStepId)); } var resolvedStartStepId = ResolveStartStepId(definition, context, startStepId); var errorStr = string.Empty; WorkflowState finalState = WorkflowState.Created; MessageKey failureMessageKey = MessageKey.None; object[] failureMessageArguments = Array.Empty(); string failureMessage = string.Empty; try { IsRunning = true; _workflowEngine = new WorkflowEngine(definition, context); _workflowEngine.Start(resolvedStartStepId); // 异步轮询等待工作流结束 // 这样可以不阻塞 UI 线程,同时保持 IsRunning 状态正确 while (_workflowEngine != null && _workflowEngine.IsWorkflowRunning) { await Task.Delay(100); } // 捕获最终状态(Dispose 之前) if (_workflowEngine != null) { finalState = _workflowEngine.CurrentState; } failureMessageKey = ResolveFailureMessageKey(context); failureMessageArguments = ResolveFailureMessageArguments(context); failureMessage = ResolveFailureMessage(context, failureMessageKey, failureMessageArguments); } finally { // 无论正常结束、异常还是被取消,都确保清理资源和复位状态 errorStr = _workflowEngine?.LastException?.ToString(); IsRunning = false; _workflowEngine?.Dispose(); _workflowEngine = null; } var completedArgs = new WorkflowRunCompletedEventArgs(finalState, errorStr, failureMessage, failureMessageKey, failureMessageArguments); RunCompleted?.Invoke(this, completedArgs); return completedArgs; } /// /// 从指定步骤启动工作流(语义化封装)。 /// public Task RunFromStepAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId) { if (string.IsNullOrWhiteSpace(startStepId)) throw new ArgumentNullException(nameof(startStepId)); return RunAsync(definition, context, startStepId); } public Task RunFromStepWithResultAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId) { if (string.IsNullOrWhiteSpace(startStepId)) throw new ArgumentNullException(nameof(startStepId)); return RunWithResultAsync(definition, context, startStepId); } private string ResolveStartStepId(WorkflowDefinition definition, WorkflowContext context, string startStepId) { if (!string.IsNullOrWhiteSpace(startStepId)) { return startStepId; } if (!context.TryGetData(WorkflowContextKeys.WorkflowName, out var workflowName) || string.IsNullOrWhiteSpace(workflowName) || !context.TryGetData(WorkflowContextKeys.ProcessResultManager, out var resultManager) || resultManager == null || !resultManager.TryGetResumeStepId(workflowName, out var resumeStepId) || !definition.ContainsStep(resumeStepId)) { return null; } return resumeStepId; } private MessageKey ResolveFailureMessageKey(WorkflowContext context) { MessageKey failureMessageKey; if (context.TryGetData(WorkflowContextKeys.WorkflowFailureMessageKey, out failureMessageKey)) { return failureMessageKey; } return MessageKey.None; } private object[] ResolveFailureMessageArguments(WorkflowContext context) { object[] failureMessageArguments; if (context.TryGetData(WorkflowContextKeys.WorkflowFailureMessageArguments, out failureMessageArguments) && failureMessageArguments != null) { return failureMessageArguments; } return Array.Empty(); } private string ResolveFailureMessage(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments) { if (failureMessageKey != MessageKey.None) { return LanguageResourceHelper.Format(failureMessageKey, failureMessageArguments); } string failureMessage; if (context.TryGetData(WorkflowContextKeys.WorkflowFailureMessage, out failureMessage) && !string.IsNullOrWhiteSpace(failureMessage)) { return failureMessage; } return string.Empty; } /// /// 请求停止当前流程 /// public async Task StopAsync() { if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning) { await _workflowEngine.StopAsync(); } } public void Pause() { if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning) { _workflowEngine.Pause(); } } public void Resume() { if (_workflowEngine != null && _workflowEngine.IsWorkflowRunning) { _workflowEngine.Resume(); } } public void Dispose() { _workflowEngine?.Dispose(); } } }