mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-20 00:06:45 +08:00
修改了logwindows输出,避免高频输出时卡死。修改了流程运行上下文,使节点具备终止分支运行的能力。
This commit is contained in:
@@ -12,32 +12,109 @@ namespace Serein.WorkBench
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
//public class TestObject
|
||||
//{
|
||||
|
||||
// public NestedObject Data { get; set; }
|
||||
|
||||
// public class NestedObject
|
||||
// {
|
||||
// public int Code { get; set; }
|
||||
// public int Code2 { get; set; }
|
||||
|
||||
// public string Tips { get; set; }
|
||||
|
||||
// }
|
||||
// public string ToUpper(string input)
|
||||
// {
|
||||
// return input.ToUpper();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
public static SereinProjectData? FlowProjectData { get; set; }
|
||||
public static string FileDataPath { get; set; } = "";
|
||||
|
||||
public App()
|
||||
{
|
||||
// TestExp();
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
base.OnExit(e);
|
||||
|
||||
// 强制关闭所有窗口
|
||||
foreach (Window window in Windows)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
// 检查是否传入了参数
|
||||
if (e.Args.Length == 1)
|
||||
{
|
||||
// 获取文件路径
|
||||
string filePath = e.Args[0];
|
||||
// 检查文件是否存在
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
MessageBox.Show($"文件未找到:{filePath}");
|
||||
Shutdown(); // 关闭应用程序
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 读取文件内容
|
||||
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
||||
FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||
FileDataPath = System.IO.Path.GetDirectoryName(filePath) ?? "";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"读取文件时发生错误:{ex.Message}");
|
||||
Shutdown(); // 关闭应用程序
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
else if(1== 1)
|
||||
{
|
||||
//string filePath = @"F:\临时\project\new project.dnf";
|
||||
|
||||
string filePath;
|
||||
//filePath = @"F:\临时\project\tmp\project.dnf";
|
||||
//filePath = @"D:\Project\C#\TestNetFramework\Net45DllTest\Net45DllTest\bin\Debug\project.dnf";
|
||||
//filePath = @"D:\Project\C#\DynamicControl\SereinFlow\Net462DllTest\bin\Debug\project.dnf";
|
||||
//filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\project.dnf";
|
||||
filePath = @"F:\临时\project\linux\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); // 读取整个文件内容
|
||||
App.FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||
App.FileDataPath =System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if false //测试 操作表达式,条件表达式
|
||||
}
|
||||
|
||||
|
||||
#if DEBUG && false
|
||||
|
||||
public class TestObject
|
||||
{
|
||||
|
||||
public NestedObject Data { get; set; }
|
||||
|
||||
public class NestedObject
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public int Code2 { get; set; }
|
||||
|
||||
public string Tips { get; set; }
|
||||
|
||||
}
|
||||
public string ToUpper(string input)
|
||||
{
|
||||
return input.ToUpper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//测试 操作表达式,条件表达式
|
||||
private void TestExp()
|
||||
{
|
||||
|
||||
#region 测试数据
|
||||
string expression = "";
|
||||
|
||||
@@ -103,76 +180,9 @@ namespace Serein.WorkBench
|
||||
Debug.WriteLine($"{str} {expression} -> " + pass);
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
base.OnExit/**/(e);
|
||||
|
||||
// 强制关闭所有窗口
|
||||
foreach (Window window in Windows)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 成功加载的工程文件
|
||||
/// </summary>
|
||||
public static SereinProjectData? FlowProjectData { get; set; }
|
||||
public static string FileDataPath { get; set; } = "";
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
// 检查是否传入了参数
|
||||
if (e.Args.Length == 1)
|
||||
{
|
||||
// 获取文件路径
|
||||
string filePath = e.Args[0];
|
||||
// 检查文件是否存在
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
{
|
||||
MessageBox.Show($"文件未找到:{filePath}");
|
||||
Shutdown(); // 关闭应用程序
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 读取文件内容
|
||||
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
||||
FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||
FileDataPath = System.IO.Path.GetDirectoryName(filePath) ?? "";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"读取文件时发生错误:{ex.Message}");
|
||||
Shutdown(); // 关闭应用程序
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
else if(1== 1)
|
||||
{
|
||||
//string filePath = @"F:\临时\project\new project.dnf";
|
||||
|
||||
string filePath;
|
||||
//filePath = @"F:\临时\project\tmp\project.dnf";
|
||||
//filePath = @"D:\Project\C#\TestNetFramework\Net45DllTest\Net45DllTest\bin\Debug\project.dnf";
|
||||
//filePath = @"D:\Project\C#\DynamicControl\SereinFlow\Net462DllTest\bin\Debug\project.dnf";
|
||||
//filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\project.dnf";
|
||||
filePath = @"F:\临时\project\linux\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); // 读取整个文件内容
|
||||
App.FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
|
||||
App.FileDataPath =System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,18 +6,24 @@ namespace Serein.WorkBench
|
||||
/// DebugWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
|
||||
/// <summary>
|
||||
/// LogWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LogWindow : Window
|
||||
{
|
||||
private StringBuilder logBuffer = new StringBuilder();
|
||||
private int logUpdateInterval = 100; // 批量更新的时间间隔(毫秒)
|
||||
private int logUpdateInterval = 500; // 批量更新的时间间隔(毫秒)
|
||||
private Timer logUpdateTimer;
|
||||
private const int MaxLines = 1000; // 最大显示的行数
|
||||
private bool autoScroll = true; // 自动滚动标识
|
||||
private int flushThreshold = 1000; // 设置日志刷新阈值
|
||||
private const int maxFlushSize = 10000; // 每次最大刷新字符数
|
||||
|
||||
public LogWindow()
|
||||
{
|
||||
@@ -39,7 +45,16 @@ namespace Serein.WorkBench
|
||||
{
|
||||
lock (logBuffer)
|
||||
{
|
||||
logBuffer.Append(text); // 将日志添加到缓冲区中
|
||||
logBuffer.Append(text);
|
||||
|
||||
// 异步写入日志到文件
|
||||
// Task.Run(() => File.AppendAllText("log.txt", text));
|
||||
|
||||
// 如果日志达到阈值,立即刷新
|
||||
if (logBuffer.Length > flushThreshold)
|
||||
{
|
||||
FlushLog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,17 +65,27 @@ namespace Serein.WorkBench
|
||||
{
|
||||
if (logBuffer.Length == 0) return;
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
lock (logBuffer)
|
||||
{
|
||||
LogTextBox.AppendText(logBuffer.ToString());
|
||||
logBuffer.Clear(); // 清空缓冲区
|
||||
// 仅追加部分日志,避免一次更新过多内容
|
||||
string logContent = logBuffer.Length > maxFlushSize
|
||||
? logBuffer.ToString(0, maxFlushSize)
|
||||
: logBuffer.ToString();
|
||||
logBuffer.Remove(0, logContent.Length); // 清空已更新的部分
|
||||
|
||||
LogTextBox.AppendText(logContent);
|
||||
}
|
||||
|
||||
TrimLog(); // 检查并修剪日志长度
|
||||
ScrollToEndIfNeeded(); // 根据条件滚动到末尾
|
||||
});
|
||||
// 不必每次都修剪日志,当行数超过限制20%时再修剪
|
||||
if (LogTextBox.LineCount > MaxLines * 1.2)
|
||||
{
|
||||
TrimLog();
|
||||
}
|
||||
|
||||
ScrollToEndIfNeeded(); // 根据是否需要自动滚动来决定
|
||||
}, System.Windows.Threading.DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,7 +96,8 @@ namespace Serein.WorkBench
|
||||
if (LogTextBox.LineCount > MaxLines)
|
||||
{
|
||||
// 删除最早的多余行
|
||||
LogTextBox.Text = LogTextBox.Text.Substring(LogTextBox.GetCharacterIndexFromLineIndex(LogTextBox.LineCount - MaxLines));
|
||||
LogTextBox.Text = LogTextBox.Text.Substring(
|
||||
LogTextBox.GetCharacterIndexFromLineIndex(LogTextBox.LineCount - MaxLines));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +109,7 @@ namespace Serein.WorkBench
|
||||
if (e.ExtentHeightChange == 0) // 用户手动滚动时
|
||||
{
|
||||
// 判断是否滚动到底部
|
||||
// autoScroll = LogTextBox.VerticalOffset == LogTextBox.ScrollableHeight;
|
||||
//autoScroll = LogTextBox.VerticalOffset == LogTextBox.ScrollableHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,9 +148,6 @@ namespace Serein.WorkBench
|
||||
/// </summary>
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
//logUpdateTimer?.Stop();
|
||||
//logUpdateTimer?.Close();
|
||||
//logUpdateTimer?.Dispose();
|
||||
logBuffer?.Clear();
|
||||
Clear();
|
||||
e.Cancel = true; // 取消关闭操作
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Serein.WorkBench"
|
||||
xmlns:tool="clr-namespace:Serein.WorkBench.Tool.Converters"
|
||||
xmlns:nodeView="clr-namespace:Serein.WorkBench.Node.View"
|
||||
xmlns:themes="clr-namespace:Serein.WorkBench.Themes"
|
||||
Title="Dynamic Node Flow" Height="900" Width="1400"
|
||||
@@ -13,10 +14,10 @@
|
||||
Closing="Window_Closing">
|
||||
|
||||
<Window.Resources>
|
||||
<local:RightThumbPositionConverter x:Key="RightThumbPositionConverter" />
|
||||
<local:BottomThumbPositionConverter x:Key="BottomThumbPositionConverter" />
|
||||
<local:VerticalCenterThumbPositionConverter x:Key="VerticalCenterThumbPositionConverter" />
|
||||
<local:HorizontalCenterThumbPositionConverter x:Key="HorizontalCenterThumbPositionConverter" />
|
||||
<tool:RightThumbPositionConverter x:Key="RightThumbPositionConverter" />
|
||||
<tool:BottomThumbPositionConverter x:Key="BottomThumbPositionConverter" />
|
||||
<tool:VerticalCenterThumbPositionConverter x:Key="VerticalCenterThumbPositionConverter" />
|
||||
<tool:HorizontalCenterThumbPositionConverter x:Key="HorizontalCenterThumbPositionConverter" />
|
||||
</Window.Resources>
|
||||
|
||||
<Window.InputBindings>
|
||||
|
||||
@@ -939,7 +939,7 @@ namespace Serein.WorkBench
|
||||
|
||||
|
||||
contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => FlowEnvironment.SetStartNode(nodeGuid)));
|
||||
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) => FlowEnvironment.RemoteNode(nodeGuid)));
|
||||
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) => FlowEnvironment.RemoveNode(nodeGuid)));
|
||||
|
||||
contextMenu.Items.Add(CreateMenuItem("添加 真分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsSucceed)));
|
||||
contextMenu.Items.Add(CreateMenuItem("添加 假分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsFail)));
|
||||
@@ -1016,7 +1016,7 @@ namespace Serein.WorkBench
|
||||
// 获取起始节点与终止节点,消除映射关系
|
||||
var fromNodeGuid = connectionToRemove.Start.ViewModel.Node.Guid;
|
||||
var toNodeGuid = connectionToRemove.End.ViewModel.Node.Guid;
|
||||
FlowEnvironment.RemoteConnect(fromNodeGuid, toNodeGuid, connection.Type);
|
||||
FlowEnvironment.RemoveConnect(fromNodeGuid, toNodeGuid, connection.Type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1392,7 +1392,7 @@ namespace Serein.WorkBench
|
||||
if (node is not null && node.MethodDetails?.ReturnType != typeof(void))
|
||||
{
|
||||
var key = node.Guid;
|
||||
var instance = node.GetFlowData();
|
||||
var instance = node.GetFlowData(); // 对象预览树视图获取(后期更改)
|
||||
if(instance is not null)
|
||||
{
|
||||
ViewObjectViewer.LoadObjectInformation(key, instance);
|
||||
@@ -1864,7 +1864,7 @@ namespace Serein.WorkBench
|
||||
var guid = node?.ViewModel?.Node?.Guid;
|
||||
if (!string.IsNullOrEmpty(guid))
|
||||
{
|
||||
FlowEnvironment.RemoteNode(guid);
|
||||
FlowEnvironment.RemoveNode(guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2371,9 +2371,9 @@ namespace Serein.WorkBench
|
||||
{
|
||||
logWindow?.Show();
|
||||
|
||||
await FlowEnvironment.StartAsync(); // 快
|
||||
// await FlowEnvironment.StartAsync(); // 快
|
||||
|
||||
//await Task.Run(FlowEnvironment.StartAsync); // 上下文多次切换的场景中慢了1/10,定时器精度丢失
|
||||
await Task.Run(FlowEnvironment.StartAsync); // 上下文多次切换的场景中慢了1/10,定时器精度丢失
|
||||
//await Task.Factory.StartNew(FlowEnvironment.StartAsync); // 慢了1/5,定时器精度丢失
|
||||
}
|
||||
|
||||
|
||||
@@ -54,19 +54,23 @@ namespace Serein.WorkBench.Themes
|
||||
Key = key,
|
||||
Instance = instance,
|
||||
};
|
||||
TextBlock textBlock = new TextBlock();
|
||||
textBlock.Text = key;
|
||||
textBlock.Tag = iOCObj;
|
||||
textBlock.MouseDown += (s, e) =>
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if(s is TextBlock block && block.Tag is IOCObj iocObj)
|
||||
TextBlock textBlock = new TextBlock();
|
||||
textBlock.Text = key;
|
||||
textBlock.Tag = iOCObj;
|
||||
textBlock.MouseDown += (s, e) =>
|
||||
{
|
||||
SelectObj?.Invoke(iocObj.Key, iocObj.Instance);
|
||||
//FlowEnvironment.SetMonitorObjState(iocObj.Instance, true); // 通知环境,该节点的数据更新后需要传到UI
|
||||
}
|
||||
};
|
||||
DependenciesListBox.Items.Add(textBlock);
|
||||
SortLisbox(DependenciesListBox);
|
||||
if (s is TextBlock block && block.Tag is IOCObj iocObj)
|
||||
{
|
||||
SelectObj?.Invoke(iocObj.Key, iocObj.Instance);
|
||||
//FlowEnvironment.SetMonitorObjState(iocObj.Instance, true); // 通知环境,该节点的数据更新后需要传到UI
|
||||
}
|
||||
};
|
||||
DependenciesListBox.Items.Add(textBlock);
|
||||
SortLisbox(DependenciesListBox);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,6 +9,9 @@ using System.Windows;
|
||||
|
||||
namespace Serein.WorkBench.Tool.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据bool类型控制可见性
|
||||
/// </summary>
|
||||
[ValueConversion(typeof(bool), typeof(Visibility))]
|
||||
public class InvertableBooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
|
||||
@@ -5,8 +5,11 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Serein.WorkBench
|
||||
namespace Serein.WorkBench.Tool.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class RightThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
@@ -21,7 +24,9 @@ namespace Serein.WorkBench
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class BottomThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
@@ -36,13 +41,15 @@ namespace Serein.WorkBench
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class VerticalCenterThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double height)
|
||||
return (height / 2) - 5; // Centering Thumb vertically
|
||||
return height / 2 - 5; // Centering Thumb vertically
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,13 +58,15 @@ namespace Serein.WorkBench
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class HorizontalCenterThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double width)
|
||||
return (width / 2) - 5; // Centering Thumb horizontally
|
||||
return width / 2 - 5; // Centering Thumb horizontally
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ using System.Windows.Media;
|
||||
|
||||
namespace Serein.WorkBench.Tool.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据控件类型切换颜色
|
||||
/// </summary>
|
||||
public class TypeToColorConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
|
||||
Reference in New Issue
Block a user