mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
优化了运行。在运行状态下,在画布上添加触发器、移除触发器、或者涉及到触发器的操作都会及时/延时生效(已经在等待信号的触发器,将会在触发信号后才会拿取新的信号类型创建触发任务)
This commit is contained in:
@@ -141,7 +141,7 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据类型生成对应的实例,并注入其中的依赖项(类型信息不登记到IOC容器中)
|
/// 根据类型生成对应的实例,并注入其中的依赖项(类型信息不登记到IOC容器中),类型创建后自动注入其它需要此类型的对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="controllerType"></param>
|
/// <param name="controllerType"></param>
|
||||||
/// <param name="parameters"></param>
|
/// <param name="parameters"></param>
|
||||||
|
|||||||
@@ -399,11 +399,19 @@ namespace Serein.Library.Web
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// If serialization fails, use the original message's string representation
|
// If serialization fails, use the original message's string representation
|
||||||
|
try
|
||||||
|
{
|
||||||
resultData = ex.ToString();
|
resultData = ex.ToString();
|
||||||
byte[] buffer = Encoding.UTF8.GetBytes(resultData);
|
byte[] buffer = Encoding.UTF8.GetBytes(resultData);
|
||||||
response.ContentLength64 = buffer.Length;
|
response.ContentLength64 = buffer.Length;
|
||||||
response.OutputStream.Write(buffer, 0, buffer.Length);
|
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex1)
|
||||||
|
{
|
||||||
|
|
||||||
|
Console.WriteLine(ex1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event FlowRunCompleteHandler OnFlowRunComplete;
|
public event FlowRunCompleteHandler OnFlowRunComplete;
|
||||||
|
|
||||||
private FlowStarter? nodeFlowStarter = null;
|
private FlowStarter? flowStarter = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 一种轻量的IOC容器
|
/// 一种轻量的IOC容器
|
||||||
@@ -117,6 +117,7 @@ namespace Serein.NodeFlow
|
|||||||
/// 私有属性
|
/// 私有属性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private NodeModelBase _startNode;
|
private NodeModelBase _startNode;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 起始节点
|
/// 起始节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -143,7 +144,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task StartAsync()
|
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)
|
List<SingleFlipflopNode> flipflopNodes = Nodes.Values.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop && it.IsStart == false)
|
||||||
.Select(it => (SingleFlipflopNode)it)
|
.Select(it => (SingleFlipflopNode)it)
|
||||||
.Where(node => node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
|
.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();
|
var exitMethods = MethodDetailss.Where(it => it.MethodDynamicType == NodeType.Exit).ToList();
|
||||||
|
|
||||||
|
|
||||||
await nodeFlowStarter.RunAsync(StartNode,
|
await flowStarter.RunAsync(StartNode,
|
||||||
this,
|
this,
|
||||||
runMethodDetailess,
|
runMethodDetailess,
|
||||||
initMethods,
|
initMethods,
|
||||||
@@ -162,15 +163,15 @@ namespace Serein.NodeFlow
|
|||||||
exitMethods,
|
exitMethods,
|
||||||
flipflopNodes);
|
flipflopNodes);
|
||||||
|
|
||||||
if(nodeFlowStarter?.FlipFlopState == RunState.NoStart)
|
if(flowStarter?.FlipFlopState == RunState.NoStart)
|
||||||
{
|
{
|
||||||
this.Exit(); // 未运行触发器时,才会调用结束方法
|
this.Exit(); // 未运行触发器时,才会调用结束方法
|
||||||
}
|
}
|
||||||
nodeFlowStarter = null;
|
flowStarter = null;
|
||||||
}
|
}
|
||||||
public void Exit()
|
public void Exit()
|
||||||
{
|
{
|
||||||
nodeFlowStarter?.Exit();
|
flowStarter?.Exit();
|
||||||
OnFlowRunComplete?.Invoke(new FlowEventArgs());
|
OnFlowRunComplete?.Invoke(new FlowEventArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,9 +342,6 @@ namespace Serein.NodeFlow
|
|||||||
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
|
OnProjectLoaded?.Invoke(new ProjectLoadedEventArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存项目为项目文件
|
/// 保存项目为项目文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -381,6 +379,15 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
var nodeModel = CreateNode(nodeControlType, methodDetails);
|
var nodeModel = CreateNode(nodeControlType, methodDetails);
|
||||||
TryAddNode(nodeModel);
|
TryAddNode(nodeModel);
|
||||||
|
|
||||||
|
if(flowStarter?.FlowState != RunState.Completion
|
||||||
|
&& nodeControlType == NodeControlType.Flipflop
|
||||||
|
&& nodeModel is SingleFlipflopNode flipflopNode)
|
||||||
|
{
|
||||||
|
// 当前添加节点属于触发器,且当前正在运行,则加载到运行环境中
|
||||||
|
flowStarter?.AddFlipflopInRuning(flipflopNode, this);
|
||||||
|
}
|
||||||
|
|
||||||
// 通知UI更改
|
// 通知UI更改
|
||||||
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
|
OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, position));
|
||||||
// 因为需要UI先布置了元素,才能通知UI变更特效
|
// 因为需要UI先布置了元素,才能通知UI变更特效
|
||||||
@@ -391,8 +398,6 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除节点
|
/// 移除节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -432,15 +437,18 @@ namespace Serein.NodeFlow
|
|||||||
// 遍历所有子节点,从那些子节点中的父节点集合移除该节点
|
// 遍历所有子节点,从那些子节点中的父节点集合移除该节点
|
||||||
foreach (var snc in remoteNode.SuccessorNodes)
|
foreach (var snc in remoteNode.SuccessorNodes)
|
||||||
{
|
{
|
||||||
var sCType = snc.Key; // 连接类型
|
var connectionType = snc.Key; // 连接类型
|
||||||
for (int i = 0; i < snc.Value.Count; i++)
|
for (int i = 0; i < snc.Value.Count; i++)
|
||||||
{
|
{
|
||||||
NodeModelBase? sNode = snc.Value[i];
|
NodeModelBase? toNode = snc.Value[i];
|
||||||
remoteNode.SuccessorNodes[sCType].RemoveAt(i);
|
|
||||||
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
|
RemoteConnect(remoteNode, toNode, connectionType);
|
||||||
sNode.Guid,
|
//remoteNode.SuccessorNodes[connectionType].RemoveAt(i);
|
||||||
sCType,
|
|
||||||
NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
|
//OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(remoteNode.Guid,
|
||||||
|
// toNode.Guid,
|
||||||
|
// connectionType,
|
||||||
|
// NodeConnectChangeEventArgs.ConnectChangeType.Remote)); // 通知UI
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,9 +483,9 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除连接关系
|
/// 移除连接关系
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fromNodeGuid"></param>
|
/// <param name="fromNodeGuid">起始节点Guid</param>
|
||||||
/// <param name="toNodeGuid"></param>
|
/// <param name="toNodeGuid">目标节点Guid</param>
|
||||||
/// <param name="connectionType"></param>
|
/// <param name="connectionType">连接关系</param>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
public void RemoteConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
||||||
{
|
{
|
||||||
@@ -490,11 +498,41 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
return;
|
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);
|
fromNode.SuccessorNodes[connectionType].Remove(toNode);
|
||||||
toNode.PreviousNodes[connectionType].Remove(fromNode);
|
toNode.PreviousNodes[connectionType].Remove(fromNode);
|
||||||
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNodeGuid,
|
if(toNode is SingleFlipflopNode flipflopNode)
|
||||||
toNodeGuid,
|
{
|
||||||
|
if (flowStarter?.FlowState != RunState.Completion
|
||||||
|
&& flipflopNode.NotExitPreviousNode())
|
||||||
|
{
|
||||||
|
// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
|
||||||
|
flowStarter?.AddFlipflopInRuning(flipflopNode, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知UI
|
||||||
|
OnNodeConnectChange?.Invoke(new NodeConnectChangeEventArgs(fromNode.Guid,
|
||||||
|
toNode.Guid,
|
||||||
connectionType,
|
connectionType,
|
||||||
NodeConnectChangeEventArgs.ConnectChangeType.Remote));
|
NodeConnectChangeEventArgs.ConnectChangeType.Remote));
|
||||||
}
|
}
|
||||||
@@ -789,10 +827,6 @@ namespace Serein.NodeFlow
|
|||||||
return controlType;
|
return controlType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
|
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
|
||||||
{
|
{
|
||||||
ConnectionType[] ct = [ConnectionType.IsSucceed,
|
ConnectionType[] ct = [ConnectionType.IsSucceed,
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 执行初始化,绑定IOC容器,再执行加载时,设置流程退出时的回调函数
|
#region 执行初始化,绑定IOC容器,再执行加载时
|
||||||
|
|
||||||
object?[]? args = [Context];
|
object?[]? args = [Context];
|
||||||
foreach (var md in initMethods) // 初始化
|
foreach (var md in initMethods) // 初始化
|
||||||
@@ -172,6 +172,9 @@ namespace Serein.NodeFlow
|
|||||||
md.MethodDelegate.DynamicInvoke(data);
|
md.MethodDelegate.DynamicInvoke(data);
|
||||||
}
|
}
|
||||||
Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
Context.SereinIoc.Build(); // 预防有人在加载时才注册类型,再绑定一次
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 设置流程退出时的回调函数
|
||||||
ExitAction = () =>
|
ExitAction = () =>
|
||||||
{
|
{
|
||||||
SereinIOC.Run<WebServer>(web => {
|
SereinIOC.Run<WebServer>(web => {
|
||||||
@@ -193,9 +196,6 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
FlowState = RunState.Completion;
|
FlowState = RunState.Completion;
|
||||||
FlipFlopState = RunState.Completion;
|
FlipFlopState = RunState.Completion;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -233,6 +233,17 @@ namespace Serein.NodeFlow
|
|||||||
#endregion
|
#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>
|
||||||
/// 启动触发器
|
/// 启动触发器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -248,26 +259,39 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
while (!FlipFlopCts.IsCancellationRequested) // 循环中直到栈为空才会退出
|
while (!FlipFlopCts.IsCancellationRequested) // 循环中直到栈为空才会退出
|
||||||
{
|
{
|
||||||
|
if(singleFlipFlopNode.NotExitPreviousNode() == false)
|
||||||
|
{
|
||||||
|
// 存在上级节点时,退出触发器
|
||||||
|
break;
|
||||||
|
}
|
||||||
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
|
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
|
||||||
// 调用委托并获取结果
|
// 调用委托并获取结果
|
||||||
|
|
||||||
md.ActingInstance = context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
|
md.ActingInstance = context.SereinIoc.GetOrRegisterInstantiate(md.ActingInstanceType);
|
||||||
|
|
||||||
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
IFlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
||||||
|
|
||||||
ConnectionType connection = flipflopContext.State.ToContentType();
|
ConnectionType connection = flipflopContext.State.ToContentType();
|
||||||
|
|
||||||
|
|
||||||
if (connection != ConnectionType.None)
|
if (connection != ConnectionType.None)
|
||||||
{
|
{
|
||||||
singleFlipFlopNode.NextOrientation = connection;
|
singleFlipFlopNode.NextOrientation = connection;
|
||||||
singleFlipFlopNode.FlowData = flipflopContext.Data;
|
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);
|
var context = new DynamicContext(SereinIOC,flowEnvironment);
|
||||||
nextNode.PreviousNode = singleFlipFlopNode;
|
nextNode.PreviousNode = singleFlipFlopNode;
|
||||||
return nextNode.StartExecution(context);
|
return nextNode.StartExecution(context);
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
Task[] tasks = [..upstreamNodeTasks, .. tmpTasks];
|
||||||
Task.WaitAll(tasks);
|
Task.WaitAll(tasks);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
不定期在Bilibili个人空间上更新相关的视频。
|
不定期在Bilibili个人空间上更新相关的视频。
|
||||||
https://space.bilibili.com/33526379
|
https://space.bilibili.com/33526379
|
||||||
|
|
||||||
# 当前任务 2024年9月15日22:04:40
|
# 计划任务 2024年9月17日更新
|
||||||
* 计划新增基础节点“属性包装器”,用来收集各个节点的数据,包装成匿名对象/Json类型
|
* (重要+优先)正在计划实现断点功能,查看运行中节点的数据、ioc容器对象
|
||||||
* 计划编写网络方面的通讯,方便传出、传入数据
|
* 正在计划新增基础节点“属性包装器”,用来收集各个节点的数据,包装成匿名对象/Json类型
|
||||||
* 包装数据类型, 优化传递效率(尽可能避免拆箱、装箱)
|
* 正在计划实现网络方面的通讯,方便传出、传入数据
|
||||||
|
* 正在计划实现对数据传递的包装, 尽可能避免拆箱、装箱,优化传递效率。(可能做不到)
|
||||||
|
|
||||||
|
|
||||||
# 如何加载我的DLL?
|
# 如何加载我的DLL?
|
||||||
|
|||||||
@@ -150,14 +150,14 @@ namespace Serein.WorkBench
|
|||||||
Shutdown(); // 关闭应用程序
|
Shutdown(); // 关闭应用程序
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else if (1 == 1)
|
else if (1 == 1)
|
||||||
//{
|
{
|
||||||
// string filePath = @"F:\临时\project\new project.dnf";
|
string filePath = @"F:\临时\project\new project.dnf";
|
||||||
// //string filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\U9 project.dnf";
|
//string filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\U9 project.dnf";
|
||||||
// string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
||||||
// App.FData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
App.FData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||||
// App.FileDataPath = filePath;//System.IO.Path.GetDirectoryName(filePath)!;
|
App.FileDataPath = filePath;//System.IO.Path.GetDirectoryName(filePath)!;
|
||||||
//}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user