Files
serein-flow/Library/DynamicFlow/NodeFlowStarter.cs

178 lines
6.2 KiB
C#
Raw Normal View History

2024-08-05 10:11:58 +08:00
using Serein;
using Serein.DynamicFlow;
using Serein.DynamicFlow.NodeModel;
using Serein.DynamicFlow.Tool;
using Serein.Web;
using SqlSugar;
using System;
2024-08-05 10:11:58 +08:00
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
2024-08-05 10:11:58 +08:00
namespace DynamicDemo.Node
{
public class NodeRunTcs: CancellationTokenSource
{
}
2024-08-05 10:11:58 +08:00
public class NodeFlowStarter(IServiceContainer serviceContainer,List<MethodDetails> methodDetails)
2024-08-05 10:11:58 +08:00
{
private readonly IServiceContainer ServiceContainer = serviceContainer;
private readonly List<MethodDetails> methodDetails = methodDetails;
2024-08-05 10:11:58 +08:00
private Action ExitAction = null;
2024-08-05 10:11:58 +08:00
private DynamicContext context = null;
2024-08-05 10:11:58 +08:00
public NodeRunTcs MainCts;
/// <summary>
/// 运行测试
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
//public async Task RunAsync1(List<NodeBase> nodes)
//{
// await Task.Run(async ()=> await StartRunAsync(nodes));
//}
2024-08-05 10:11:58 +08:00
public async Task RunAsync(List<NodeBase> nodes)
{
var startNode = nodes.FirstOrDefault(p => p.IsStart);
if (startNode == null) { return; }
context = new(ServiceContainer);
MainCts = ServiceContainer.CreateServiceInstance<NodeRunTcs>();
var initMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Init).ToList();
var loadingMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Loading).ToList();
var exitMethods = methodDetails.Where(it => it.MethodDynamicType == DynamicNodeType.Exit).ToList();
ExitAction = () =>
{
ServiceContainer.Run<WebServer>((web) =>
{
web?.Stop();
});
foreach (MethodDetails? md in exitMethods)
{
object?[]? args = [context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
if(context != null && context.NodeRunCts != null && !context.NodeRunCts.IsCancellationRequested)
{
context.NodeRunCts.Cancel();
}
if (MainCts!=null && !MainCts.IsCancellationRequested) MainCts.Cancel();
ServiceContainer.Reset();
};
foreach (var md in initMethods) // 初始化 - 调用方法
{
//md.ActingInstance = context.ServiceContainer.Get(md.ActingInstanceType);
object?[]? args = [context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
context.Biuld();
foreach (var md in loadingMethods) // 加载
{
//md.ActingInstance = context.ServiceContainer.Get(md.ActingInstanceType);
object?[]? args = [context];
object?[]? data = [md.ActingInstance, args];
md.MethodDelegate.DynamicInvoke(data);
}
var flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == DynamicNodeType.Flipflop
&& it.PreviousNodes.Count == 0
&& it.IsStart != true).ToArray();
var singleFlipflopNodes = flipflopNodes.Select(it => (SingleFlipflopNode)it).ToArray();
// 使用 TaskCompletionSource 创建未启动的任务
var tasks = singleFlipflopNodes.Select(async node =>
{
await FlipflopExecute(node);
}).ToArray();
try
{
await Task.WhenAll([startNode.ExecuteStack(context),.. tasks]);
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
}
private async Task FlipflopExecute(SingleFlipflopNode singleFlipFlopNode)
{
DynamicContext context = new DynamicContext(ServiceContainer);
MethodDetails md = singleFlipFlopNode.MethodDetails;
try
{
2024-08-05 10:11:58 +08:00
if (!DelegateCache.GlobalDicDelegates.TryGetValue(md.MethodName, out Delegate del))
{
return;
}
2024-08-05 10:11:58 +08:00
var func = md.ExplicitDatas.Length == 0 ? ((Func<object, object, Task<FlipflopContext>>)del) : ((Func<object, object[], Task<FlipflopContext>>)del);
while (!MainCts.IsCancellationRequested) // 循环中直到栈为空才会退出
{
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
// 调用委托并获取结果
2024-08-05 10:11:58 +08:00
FlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
2024-08-05 10:11:58 +08:00
if (flipflopContext == null)
{
break;
}
else if (flipflopContext.State == FfState.Cancel)
{
break;
}
else if (flipflopContext.State == FfState.Succeed)
{
singleFlipFlopNode.FlowState = true;
singleFlipFlopNode.FlowData = flipflopContext.Data;
var tasks = singleFlipFlopNode.SucceedBranch.Select(nextNode =>
2024-08-05 10:11:58 +08:00
{
var context = new DynamicContext(ServiceContainer);
nextNode.PreviousNode = singleFlipFlopNode;
return nextNode.ExecuteStack(context);
}).ToArray();
Task.WaitAll(tasks);
}
}
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.ToString());
}
}
public void Exit()
{
ExitAction?.Invoke();
}
}
}