流程上下文添加了调用信息记录

This commit is contained in:
fengjiayi
2025-07-28 17:38:51 +08:00
parent ccb8e49abc
commit 74961fa2c4
22 changed files with 480 additions and 144 deletions

View File

@@ -185,12 +185,11 @@ namespace Serein.NodeFlow.Env
#if DEBUG
FlowResult flowResult = await BenchmarkHelpers.BenchmarkAsync(async () =>
{
var flowResult = await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
return flowResult;
});
await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel));
#else
FlowResult flowResult = await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
//FlowResult flowResult = await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel);
FlowResult flowResult = await BenchmarkHelpers.BenchmarkAsync(async () => await flowTaskManagement.StartFlowInSelectNodeAsync(nodeModel));
#endif

View File

@@ -412,9 +412,7 @@ namespace Serein.NodeFlow.Env
{
try
{
var nodes = canvasModel.Nodes.ToList();
nodes.Add(nodeModel);
canvasModel.Nodes = nodes;
canvasModel.Nodes = [.. canvasModel.Nodes, nodeModel];
}
catch (Exception ex)
{

View File

@@ -146,11 +146,11 @@ namespace Serein.NodeFlow.Env
/// <inheritdoc/>
public RunState FlowState { get => currentFlowEnvironment.FlowState; set => currentFlowEnvironment.FlowState = value; }
/// <inheritdoc/>
/* /// <inheritdoc/>
public void ActivateFlipflopNode(string nodeGuid)
{
currentFlowEnvironment.FlowControl.ActivateFlipflopNode(nodeGuid);
}
}*/
/* /// <inheritdoc/>
public async Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token)
@@ -167,10 +167,10 @@ namespace Serein.NodeFlow.Env
}*/
/// <inheritdoc/>
public async Task<bool> ExitFlowAsync()
/* public async Task<bool> ExitFlowAsync()
{
return await currentFlowEnvironment.FlowControl.ExitFlowAsync();
}
}*/
/* /// <inheritdoc/>
public void ExitRemoteEnv()
@@ -221,11 +221,11 @@ namespace Serein.NodeFlow.Env
SetProjectLoadingFlag(true);
}
/// <inheritdoc/>
/* /// <inheritdoc/>
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
{
currentFlowEnvironment.FlowControl.MonitorObjectNotification(nodeGuid, monitorData, sourceType);
}
}*/
/// <inheritdoc/>
public bool TryUnloadLibrary(string assemblyName)
@@ -274,7 +274,7 @@ namespace Serein.NodeFlow.Env
#endif
#endregion
/*
/// <inheritdoc/>
public async Task<bool> StartFlowAsync(string[] canvasGuids)
@@ -286,7 +286,7 @@ namespace Serein.NodeFlow.Env
public async Task<TResult> StartFlowAsync<TResult>(string startNodeGuid)
{
return await currentFlowEnvironment.FlowControl.StartFlowAsync<TResult>(startNodeGuid);
}
}*/
/* /// <inheritdoc/>
public async Task StartRemoteServerAsync(int port = 7525)
@@ -299,7 +299,7 @@ namespace Serein.NodeFlow.Env
{
currentFlowEnvironment.StopRemoteServer();
}*/
/*
/// <inheritdoc/>
public void TerminateFlipflopNode(string nodeGuid)
{
@@ -310,7 +310,7 @@ namespace Serein.NodeFlow.Env
public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type)
{
currentFlowEnvironment.FlowControl.TriggerInterrupt(nodeGuid, expression, type);
}
}*/
/// <inheritdoc/>
public void SetUIContextOperation(UIContextOperation uiContextOperation)
@@ -318,12 +318,12 @@ namespace Serein.NodeFlow.Env
currentFlowEnvironment.SetUIContextOperation(uiContextOperation);
}
/*
/// <inheritdoc/>
public void UseExternalIOC(ISereinIOC ioc)
{
currentFlowEnvironment.FlowControl.UseExternalIOC(ioc);
}
}*/
/// <inheritdoc/>
public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel)

View File

@@ -40,7 +40,6 @@ namespace Serein.NodeFlow.Model
return;
}
/// <summary>
/// 执行节点对应的方法
/// </summary>
@@ -50,7 +49,6 @@ namespace Serein.NodeFlow.Model
/// <returns>节点传回数据对象</returns>
public virtual async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
{
// 执行触发检查是否需要中断
if (DebugSetting.IsInterrupt)
{

View File

@@ -25,6 +25,8 @@ namespace Serein.NodeFlow.Model
/// </summary>
public partial class SingleGlobalDataNode : NodeModelBase, INodeContainer
{
string INodeContainer.Guid => this.Guid;
/// <summary>
/// 全局数据节点是基础节点
/// </summary>
@@ -58,12 +60,13 @@ namespace Serein.NodeFlow.Model
DataNode = nodeModel;
return true;
}
else
else if (DataNode.Guid != nodeModel.Guid)
{
// 全局数据节点只有一个子控件
Env.FlowEdit.TakeOutNodeToContainer(DataNode.CanvasDetails.Guid, DataNode.Guid);
Env.FlowEdit.PlaceNodeToContainer(this.CanvasDetails.Guid, nodeModel.Guid, this.Guid);
return false;
}
return false;
}

View File

@@ -78,21 +78,29 @@ namespace Serein.NodeFlow.Model.Operation
public override async Task<bool> ExecuteAsync()
{
if (!ValidationParameter()) return false;
ContainerNode.PlaceNode(Node);
await TriggerEvent(() =>
var isSuccess = ContainerNode.PlaceNode(Node);
if(isSuccess is true)
{
flowEnvironmentEvent.OnNodePlace(new NodePlaceEventArgs(CanvasGuid, NodeGuid, ContainerNodeGuid)); // 通知UI更改节点放置位置
});
return true;
await TriggerEvent(() =>
{
flowEnvironmentEvent.OnNodePlace(new NodePlaceEventArgs(CanvasGuid, NodeGuid, ContainerNodeGuid)); // 通知UI更改节点放置位置
});
}
return isSuccess;
}
public override bool Undo()
{
ContainerNode.TakeOutNode(Node);
flowEnvironmentEvent.OnNodeTakeOut(new NodeTakeOutEventArgs(CanvasGuid, NodeGuid)); // 重新放置在画布上
return true;
var isSuccess = ContainerNode.TakeOutNode(Node);
if (isSuccess is true)
{
_ = TriggerEvent(() =>
{
// 取出节点,重新放置在画布上
flowEnvironmentEvent.OnNodeTakeOut(new NodeTakeOutEventArgs(CanvasGuid, ContainerNode.Guid, NodeGuid));
});
}
return isSuccess;
}

View File

@@ -65,23 +65,29 @@ namespace Serein.NodeFlow.Model.Operation
{
if (!ValidationParameter()) return false;
ContainerNode.TakeOutNode(Node);
await TriggerEvent(() =>
var isSuccess = ContainerNode.TakeOutNode(Node);
if (isSuccess is true)
{
flowEnvironmentEvent.OnNodeTakeOut(new NodeTakeOutEventArgs(CanvasGuid, NodeGuid)); // 重新放置在画布上
});
return true;
await TriggerEvent(() =>
{
// 取出节点,重新放置在画布上
flowEnvironmentEvent.OnNodeTakeOut(new NodeTakeOutEventArgs(CanvasGuid, ContainerNode.Guid, NodeGuid));
});
}
return isSuccess;
}
public override bool Undo()
{
ContainerNode.PlaceNode(Node);
if (ContainerNode is IFlowNode containerFlowNode)
var isSuccess = ContainerNode.PlaceNode(Node);
if (isSuccess is true)
{
flowEnvironmentEvent.OnNodePlace(new NodePlaceEventArgs(CanvasGuid, NodeGuid, containerFlowNode.Guid)); // 通知UI更改节点放置位置
if (ContainerNode is IFlowNode containerFlowNode)
{
flowEnvironmentEvent.OnNodePlace(new NodePlaceEventArgs(CanvasGuid, NodeGuid, containerFlowNode.Guid)); // 通知UI更改节点放置位置
}
}
return true;
return isSuccess;
}

View File

@@ -6,6 +6,9 @@ using Serein.NodeFlow.Model;
using Serein.NodeFlow.Tool;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks.Dataflow;
using System.Xml.Linq;
@@ -21,7 +24,6 @@ namespace Serein.NodeFlow.Services
/// </summary>
private ConcurrentDictionary<SingleFlipflopNode, CancellationTokenSource> dictGlobalFlipflop = [];
/// <summary>
/// 结束运行时需要执行的方法
/// </summary>
@@ -271,13 +273,65 @@ namespace Serein.NodeFlow.Services
/// <returns></returns>
public async Task<FlowResult> StartFlowInSelectNodeAsync(IFlowNode startNode)
{
var pool = WorkOptions.FlowContextPool;
var context = pool.Allocate();
var token = WorkOptions.CancellationTokenSource.Token;
var result = await startNode.StartFlowAsync(context, token); // 开始运行时从选定节点开始运行
var sw = Stopwatch.StartNew();
var checkpoints = new Dictionary<string, TimeSpan>();
var pool = WorkOptions.FlowContextPool;
var token = WorkOptions.CancellationTokenSource.Token;
var context = pool.Allocate();
checkpoints["准备Context"] = sw.Elapsed;
var result = await startNode.StartFlowAsync(context, token); // 开始运行时从选定节点开始运行
checkpoints["执行流程"] = sw.Elapsed;
if (context.IsRecordInvokeInfo)
{
var invokeInfos = context.GetAllInvokeInfos();
_ = Task.Delay(100).ContinueWith(async (task) =>
{
await task;
if(invokeInfos.Count < 255)
{
foreach (var info in invokeInfos)
{
SereinEnv.WriteLine(InfoType.INFO, info.ToString());
}
}
else
{
double total = 0;
for (int i = 0; i < invokeInfos.Count; i++)
{
total += invokeInfos[i].TS.TotalSeconds;
}
SereinEnv.WriteLine(InfoType.INFO, $"运行次数:{invokeInfos.Count}");
SereinEnv.WriteLine(InfoType.INFO, $"平均耗时:{total / invokeInfos.Count}");
SereinEnv.WriteLine(InfoType.INFO, $"总耗时:{total}");
}
});
}
context.Reset();
checkpoints["重置流程"] = sw.Elapsed;
pool.Free(context);
checkpoints["释放Context"] = sw.Elapsed;
_ = Task.Run(() =>
{
var last = TimeSpan.Zero;
foreach (var kv in checkpoints)
{
SereinEnv.WriteLine(InfoType.INFO, $"{kv.Key} 耗时: {(kv.Value - last).TotalMilliseconds} ms");
last = kv.Value;
}
});
return result;
}
@@ -295,7 +349,6 @@ namespace Serein.NodeFlow.Services
}
}
/// <summary>
/// 尝试移除全局触发器
/// </summary>