Files
Shi.Ji e31d3560bb 添加 MX-PD-盘古 项目文件
将 MX-PD-盘古 - new 目录下的所有文件添加到主仓库
2026-05-18 11:43:09 +08:00

274 lines
10 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<object>();
}
}
/// <summary>
/// 封装工作流的启动、停止和状态管理,用于手动流程的复用。
/// </summary>
public class
WorkflowRunner : PropertyChangedBase, IDisposable
{
private WorkflowEngine _workflowEngine;
private bool _isRunning;
/// <summary>
/// 流程是否正在运行
/// </summary>
public bool IsRunning
{
get { return _isRunning; }
private set { SetAndNotify(ref _isRunning, value); }
}
public event EventHandler<WorkflowRunCompletedEventArgs> RunCompleted;
/// <summary>
/// 运行单个 Activity自动包装为单步工作流
/// </summary>
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<WorkflowRunCompletedEventArgs> 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);
}
/// <summary>
/// 运行完整的工作流定义
/// </summary>
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context)
{
await RunWithResultAsync(definition, context, null);
}
public Task<WorkflowRunCompletedEventArgs> RunWithResultAsync(WorkflowDefinition definition, WorkflowContext context)
{
return RunWithResultAsync(definition, context, null);
}
/// <summary>
/// 运行完整的工作流定义,并支持从指定步骤启动。
/// </summary>
/// <param name="definition">工作流定义</param>
/// <param name="context">工作流上下文</param>
/// <param name="startStepId">可选指定起始步骤ID为 null/空时从初始步骤启动</param>
public async Task RunAsync(WorkflowDefinition definition, WorkflowContext context, string startStepId)
{
await RunWithResultAsync(definition, context, startStepId);
}
public async Task<WorkflowRunCompletedEventArgs> 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<object>();
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;
}
/// <summary>
/// 从指定步骤启动工作流(语义化封装)。
/// </summary>
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<WorkflowRunCompletedEventArgs> 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<string>(WorkflowContextKeys.WorkflowName, out var workflowName) ||
string.IsNullOrWhiteSpace(workflowName) ||
!context.TryGetData<ProcessResultManager>(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<MessageKey>(WorkflowContextKeys.WorkflowFailureMessageKey, out failureMessageKey))
{
return failureMessageKey;
}
return MessageKey.None;
}
private object[] ResolveFailureMessageArguments(WorkflowContext context)
{
object[] failureMessageArguments;
if (context.TryGetData<object[]>(WorkflowContextKeys.WorkflowFailureMessageArguments, out failureMessageArguments) &&
failureMessageArguments != null)
{
return failureMessageArguments;
}
return Array.Empty<object>();
}
private string ResolveFailureMessage(WorkflowContext context, MessageKey failureMessageKey, object[] failureMessageArguments)
{
if (failureMessageKey != MessageKey.None)
{
return LanguageResourceHelper.Format(failureMessageKey, failureMessageArguments);
}
string failureMessage;
if (context.TryGetData<string>(WorkflowContextKeys.WorkflowFailureMessage, out failureMessage) &&
!string.IsNullOrWhiteSpace(failureMessage))
{
return failureMessage;
}
return string.Empty;
}
/// <summary>
/// 请求停止当前流程
/// </summary>
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();
}
}
}