优化了运行。在运行状态下,在画布上添加触发器、移除触发器、或者涉及到触发器的操作都会及时/延时生效(已经在等待信号的触发器,将会在触发信号后才会拿取新的信号类型创建触发任务)

This commit is contained in:
fengjiayi
2024-09-17 21:43:49 +08:00
parent 86da5b3ba6
commit ee1a41ed83
6 changed files with 117 additions and 50 deletions

View File

@@ -81,7 +81,7 @@ namespace Serein.NodeFlow
/// </summary>
public event FlowRunCompleteHandler OnFlowRunComplete;
private FlowStarter? nodeFlowStarter = null;
private FlowStarter? flowStarter = null;
/// <summary>
/// 一种轻量的IOC容器
@@ -117,6 +117,7 @@ namespace Serein.NodeFlow
/// 私有属性
/// </summary>
private NodeModelBase _startNode;
/// <summary>
/// 起始节点
/// </summary>
@@ -143,7 +144,7 @@ namespace Serein.NodeFlow
/// <returns></returns>
public async Task StartAsync()
{
nodeFlowStarter = new FlowStarter();
flowStarter = new FlowStarter();
List<SingleFlipflopNode> flipflopNodes = Nodes.Values.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop && it.IsStart == false)
.Select(it => (SingleFlipflopNode)it)
.Where(node => node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
@@ -154,7 +155,7 @@ namespace Serein.NodeFlow
var exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList();
await nodeFlowStarter.RunAsync(StartNode,
await flowStarter.RunAsync(StartNode,
this,
runMethodDetailess,
initMethods,
@@ -162,15 +163,15 @@ namespace Serein.NodeFlow
exitMethods,
flipflopNodes);
if(nodeFlowStarter?.FlipFlopState == RunState.NoStart)
if(flowStarter?.FlipFlopState == RunState.NoStart)
{
this.Exit(); // 未运行触发器时,才会调用结束方法
}
nodeFlowStarter = null;
flowStarter = null;
}
public void Exit()
{
nodeFlowStarter?.Exit();
flowStarter?.Exit();
OnFlowRunComplete?.Invoke(new FlowEventArgs());
}
@@ -341,9 +342,6 @@ namespace Serein.NodeFlow
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
}
/// <summary>
/// 保存项目为项目文件
/// </summary>
@@ -381,6 +379,15 @@ namespace Serein.NodeFlow
{
var nodeModel = CreateNode(nodeControlType, methodDetails);
TryAddNode(nodeModel);
if(flowStarter?.FlowState != RunState.Completion
&& nodeControlType == NodeControlType.Flipflop
&& nodeModel is SingleFlipflopNode flipflopNode)
{
// 当前添加节点属于触发器,且当前正在运行,则加载到运行环境中
flowStarter?.AddFlipflopInRuning(flipflopNode, this);
}
// 通知UI更改
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
// 因为需要UI先布置了元素才能通知UI变更特效
@@ -391,8 +398,6 @@ namespace Serein.NodeFlow
}
}
/// <summary>
/// 移除节点
/// </summary>
@@ -432,15 +437,18 @@ namespace Serein.NodeFlow
// 遍历所有子节点,从那些子节点中的父节点集合移除该节点
foreach (var snc in remoteNode.SuccessorNodes)
{
var sCType = snc.Key; // 连接类型
var connectionType = snc.Key; // 连接类型
for (int i = 0; i < snc.Value.Count; i++)
{
NodeModelBase? sNode = snc.Value[i];
remoteNode.SuccessorNodes[sCType].RemoveAt(i);
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
sNode.Guid,
sCType,
NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
NodeModelBase? toNode = snc.Value[i];
RemoteConnect(remoteNode, toNode, connectionType);
//remoteNode.SuccessorNodes[connectionType].RemoveAt(i);
//OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
// toNode.Guid,
// connectionType,
// NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
}
}
@@ -475,9 +483,9 @@ namespace Serein.NodeFlow
/// <summary>
/// 移除连接关系
/// </summary>
/// <param name="fromNodeGuid"></param>
/// <param name="toNodeGuid"></param>
/// <param name="connectionType"></param>
/// <param name="fromNodeGuid">起始节点Guid</param>
/// <param name="toNodeGuid">目标节点Guid</param>
/// <param name="connectionType">连接关系</param>
/// <exception cref="NotImplementedException"></exception>
public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
{
@@ -490,11 +498,41 @@ namespace Serein.NodeFlow
{
return;
}
RemoteConnect(fromNode, toNode, connectionType);
//fromNode.SuccessorNodes[connectionType].Remove(toNode);
//toNode.PreviousNodes[connectionType].Remove(fromNode);
//OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
// toNodeGuid,
// connectionType,
// NodeConnectChangeEventArgs.ConnectChangeType.Remote));
}
/// <summary>
/// 移除连接关系
/// </summary>
/// <param name="fromNodeGuid">起始节点Model</param>
/// <param name="toNodeGuid">目标节点Model</param>
/// <param name="connectionType">连接关系</param>
/// <exception cref="NotImplementedException"></exception>
private void RemoteConnect(NodeModelBase fromNode, NodeModelBase toNode, ConnectionType connectionType)
{
fromNode.SuccessorNodes[connectionType].Remove(toNode);
toNode.PreviousNodes[connectionType].Remove(fromNode);
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
toNodeGuid,
if(toNode is SingleFlipflopNode flipflopNode)
{
if (flowStarter?.FlowState != RunState.Completion
&& flipflopNode.NotExitPreviousNode())
{
// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
flowStarter?.AddFlipflopInRuning(flipflopNode, this);
}
}
// 通知UI
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid,
toNode.Guid,
connectionType,
NodeConnectChangeEventArgs.ConnectChangeType.Remote));
}
@@ -789,10 +827,6 @@ namespace Serein.NodeFlow
return controlType;
}
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
{
ConnectionType[] ct = [ConnectionType.IsSucceed,

View File

@@ -157,7 +157,7 @@ namespace Serein.NodeFlow
}
#endregion
#region IOC容器退
#region IOC容器
object?[]? args = [Context];
foreach (var md in initMethods) // 初始化
@@ -172,6 +172,9 @@ namespace Serein.NodeFlow
md.MethodDelegate.DynamicInvoke(data);
}
Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次
#endregion
#region 退
ExitAction = () =>
{
SereinIOC.Run<WebServer>(web => {
@@ -193,9 +196,6 @@ namespace Serein.NodeFlow
}
FlowState = RunState.Completion;
FlipFlopState = RunState.Completion;
};
#endregion
@@ -233,6 +233,17 @@ namespace Serein.NodeFlow
#endregion
}
public void AddFlipflopInRuning(SingleFlipflopNode singleFlipFlopNode, IFlowEnvironment flowEnvironment)
{
_ = Task.Run(async () =>
{
// 设置对象
singleFlipFlopNode.MethodDetails.ActingInstance = SereinIOC.GetOrRegisterInstantiate(singleFlipFlopNode.MethodDetails.ActingInstanceType);
await FlipflopExecute(singleFlipFlopNode, flowEnvironment); // 启动触发器
});
}
/// <summary>
/// 启动触发器
/// </summary>
@@ -248,26 +259,39 @@ namespace Serein.NodeFlow
while (!FlipFlopCts.IsCancellationRequested) // 循环中直到栈为空才会退出
{
if(singleFlipFlopNode.NotExitPreviousNode() == false)
{
// 存在上级节点时,退出触发器
break;
}
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
// 调用委托并获取结果
md.ActingInstance = context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
ConnectionType connection = flipflopContext.State.ToContentType();
if (connection != ConnectionType.None)
{
singleFlipFlopNode.NextOrientation = connection;
singleFlipFlopNode.FlowData = flipflopContext.Data;
var tasks = singleFlipFlopNode.SuccessorNodes[connection].Select(nextNode =>
var upstreamNodeTasks = singleFlipFlopNode.SuccessorNodes[ConnectionType.Upstream].Select(nextNode =>
{
var context = new DynamicContext(SereinIOC, flowEnvironment);
nextNode.PreviousNode = singleFlipFlopNode;
return nextNode.StartExecution(context);
}).ToArray();
var tmpTasks = singleFlipFlopNode.SuccessorNodes[connection].Select(nextNode =>
{
var context = new DynamicContext(SereinIOC,flowEnvironment);
nextNode.PreviousNode = singleFlipFlopNode;
return nextNode.StartExecution(context);
}).ToArray();
Task[] tasks = [..upstreamNodeTasks, .. tmpTasks];
Task.WaitAll(tasks);
}
else