优化了节点加载逻辑

This commit is contained in:
fengjiayi
2025-07-08 17:37:03 +08:00
parent efe4d0a8e5
commit aa3d1763ed
8 changed files with 260 additions and 94 deletions

View File

@@ -13,23 +13,23 @@ namespace Serein.Library
/// <summary>
/// 将不会继续执行
/// </summary>
None,
None = -1,
/// <summary>
/// 上游分支(执行当前节点前会执行一次上游分支),默认执行。
/// </summary>
Upstream,
Upstream = 0,
/// <summary>
/// 真分支(表示当前节点顺利完成)
/// </summary>
IsSucceed,
IsSucceed = 1,
/// <summary>
/// 假分支(一般用于条件控件,条件为假时才会触发该类型的分支)
/// </summary>
IsFail,
IsFail = 2,
/// <summary>
/// 异常发生分支(当前节点对应的方法执行时出现非预期的异常)
/// </summary>
IsError,
IsError = 3,
}

View File

@@ -96,12 +96,17 @@ namespace Serein.Library
public static NodeInfo ToInfo(this IFlowNode nodeModel)
{
// if (MethodDetails == null) return null;
var trueNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支
/*var trueNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsSucceed].Select(item => item.Guid); // 真分支
var falseNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsFail].Select(item => item.Guid);// 假分支
var errorNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.IsError].Select(item => item.Guid);// 异常分支
var upstreamNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支
var upstreamNodes = nodeModel.SuccessorNodes[ConnectionInvokeType.Upstream].Select(item => item.Guid);// 上游分支*/
var successorNodes = nodeModel.SuccessorNodes.ToDictionary(kv => kv.Key, kv => kv.Value.Select(item => item.Guid).ToArray()); // 后继分支
var previousNodes = nodeModel.PreviousNodes.ToDictionary(kv => kv.Key, kv => kv.Value.Select(item => item.Guid).ToArray()); // 后继分支
// 生成参数列表
ParameterData[] parameterData = nodeModel.SaveParameterInfo();
ParameterData[] parameterDatas = nodeModel.SaveParameterInfo();
var nodeInfo = new NodeInfo
{
@@ -112,17 +117,19 @@ namespace Serein.Library
MethodName = nodeModel.MethodDetails?.MethodName,
Label = nodeModel.MethodDetails?.MethodAnotherName,
Type = nodeModel.ControlType.ToString(), //this.GetType().ToString(),
TrueNodes = trueNodes.ToArray(),
/*TrueNodes = trueNodes.ToArray(),
FalseNodes = falseNodes.ToArray(),
UpstreamNodes = upstreamNodes.ToArray(),
ParameterData = parameterData.ToArray(),
ErrorNodes = errorNodes.ToArray(),
ErrorNodes = errorNodes.ToArray(),*/
ParameterData = parameterDatas,
Position = nodeModel.Position,
IsProtectionParameter = nodeModel.DebugSetting.IsProtectionParameter,
IsInterrupt = nodeModel.DebugSetting.IsInterrupt,
IsEnable = nodeModel.DebugSetting.IsEnable,
ParentNodeGuid = nodeModel.ContainerNode?.Guid,
ChildNodeGuids = nodeModel.ChildrenNode.Select(item => item.Guid).ToArray(),
SuccessorNodes = successorNodes,
PreviousNodes = previousNodes,
};
nodeInfo.Position.X = Math.Round(nodeInfo.Position.X, 1);
nodeInfo.Position.Y = Math.Round(nodeInfo.Position.Y, 1);

View File

@@ -148,11 +148,11 @@ namespace Serein.Library
private void Init()
{
PreviousNodes = new Dictionary<ConnectionInvokeType, List<CallNode>>();
//PreviousNodes = new Dictionary<ConnectionInvokeType, List<CallNode>>();
SuccessorNodes = new Dictionary<ConnectionInvokeType, List<CallNode>>();
foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes)
{
PreviousNodes[ctType] = new List<CallNode>();
//PreviousNodes[ctType] = new List<CallNode>();
SuccessorNodes[ctType] = new List<CallNode>();
}
}
@@ -175,23 +175,48 @@ namespace Serein.Library
/// <summary>
/// 不同分支的父节点(流程调用)
/// </summary>
public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
//public Dictionary<ConnectionInvokeType, List<CallNode>> PreviousNodes { get; private set; }
/// <summary>
/// 不同分支的子节点(流程调用)
/// </summary>
public Dictionary<ConnectionInvokeType, List<CallNode>> SuccessorNodes { get; private set; }
public Dictionary<ConnectionInvokeType, List<CallNode>> SuccessorNodes { get; private set; }
public CallNode[][] ChildNodes { get; private set; } = new CallNode[][]
{
new CallNode[32],
new CallNode[32],
new CallNode[32],
new CallNode[32]
};
public int GetCount(ConnectionInvokeType type)
{
if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount;
if (type == ConnectionInvokeType.IsSucceed) return IsSuccessorNodeCount;
if (type == ConnectionInvokeType.IsFail) return IsFailNodeCount;
if (type == ConnectionInvokeType.IsError) return IsErrorNodeCount;
return 0;
}
public int UpstreamNodeCount { get; private set; } = 0;
public int IsSuccessorNodeCount { get; private set; } = 0;
public int IsFailNodeCount { get; private set; } = 0;
public int IsErrorNodeCount { get; private set; } = 0;
public CallNode AddChildNodeUpstream(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.Upstream;
ChildNodes[(int)connectionInvokeType][UpstreamNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
public CallNode AddChildNodeSucceed(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsSucceed;
ChildNodes[0][UpstreamNodeCount++] = callNode;
var connectionInvokeType = ConnectionInvokeType.IsSucceed;
ChildNodes[(int)connectionInvokeType][IsSuccessorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
@@ -199,6 +224,7 @@ namespace Serein.Library
public CallNode AddChildNodeFail(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsFail;
ChildNodes[(int)connectionInvokeType][IsFailNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
@@ -206,6 +232,7 @@ namespace Serein.Library
public CallNode AddChildNodeError(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsError;
ChildNodes[(int)connectionInvokeType][IsErrorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
@@ -240,7 +267,6 @@ namespace Serein.Library
private static readonly DefaultObjectPool<Stack<CallNode>> _stackPool = new DefaultObjectPool<Stack<CallNode>>(new DefaultPooledObjectPolicy<Stack<CallNode>>());
/// <summary>
/// 开始执行
@@ -282,7 +308,6 @@ namespace Serein.Library
#endregion
#region
// 首先将指定类别后继分支的所有节点逆序推入栈中
var nextNodes = currentNode.SuccessorNodes[context.NextOrientation];
for (int index = nextNodes.Count - 1; index >= 0; index--)
@@ -345,11 +370,16 @@ namespace Serein.Library
{
private readonly IFlowCallTree flowCallTree;
private readonly IFlowEnvironment flowEnvironment;
public static Serein.Library.Utils.ObjectPool<IDynamicContext> FlowContextPool { get; set; }
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
{
this.flowCallTree = flowCallTree;
this.flowEnvironment = flowEnvironment;
FlowContextPool = new Utils.ObjectPool<IDynamicContext>(() =>
{
return new DynamicContext(flowEnvironment);
});
}
public Task<object> InvokeAsync(string apiGuid, Dictionary<string, object> dict)
@@ -368,11 +398,12 @@ namespace Serein.Library
public async Task<TResult> StartFlowAsync<TResult>(string startNodeGuid)
{
IDynamicContext context = new DynamicContext(flowEnvironment);
IDynamicContext context = Serein.Library.LightweightFlowControl.FlowContextPool.Allocate();
CancellationTokenSource cts = new CancellationTokenSource();
FlowResult flowResult;
#if DEBUG
FlowResult flowResult = await BenchmarkHelpers.BenchmarkAsync(async () =>
flowResult = await BenchmarkHelpers.BenchmarkAsync(async () =>
{
var node = flowCallTree.Get(startNodeGuid);
var flowResult = await node.StartFlowAsync(context, cts.Token);
@@ -380,7 +411,19 @@ namespace Serein.Library
});
#else
var node = flowCallTree.Get(startNodeGuid);
FlowResult flowResult = await node.StartFlowAsync(context, cts.Token);
try
{
flowResult = await node.StartFlowAsync(context, cts.Token);
}
catch (global::System.Exception)
{
throw;
}
finally
{
context.Reset();
FlowContextPool.Free(context);
}
#endif
cts?.Cancel();

View File

@@ -162,6 +162,16 @@ namespace Serein.Library
/// </summary>
public string Type { get; set; }
/// <summary>
/// 父节点集合
/// </summary>
public Dictionary<ConnectionInvokeType, string[]> PreviousNodes { get; set; }
/// <summary>
/// 后续节点集合
/// </summary>
public Dictionary<ConnectionInvokeType, string[]> SuccessorNodes { get; set; }
/// <summary>
/// 真分支节点GUID
/// </summary>
@@ -189,7 +199,7 @@ namespace Serein.Library
/// <summary>
/// 父级节点Guid
/// 如果节点放置在了区域控件上,这里会有父级节点Guid
/// </summary>
public string ParentNodeGuid{ get; set; }

View File

@@ -15,7 +15,7 @@ namespace Serein.Library.Utils
/// <summary>
/// 运行指定异步方法多次并输出耗时的最大、最小和平均值。
/// </summary>
/// <param name="func">需要执行的异步方法</param>
/// <param name="action">需要执行的方法</param>
/// <param name="count">执行次数默认10000</param>
public static void Benchmark(Action action, int count = 10000)
{
@@ -38,6 +38,7 @@ namespace Serein.Library.Utils
double avg = total / count;
Console.WriteLine($"运行 {count} 次:");
Console.WriteLine($"总耗时 :{total} 毫秒:");
Console.WriteLine($"最大耗时:{max} 毫秒");
Console.WriteLine($"最小耗时:{min} 毫秒");
Console.WriteLine($"平均耗时:{avg} 毫秒");