更改了日志输出,更改了ChannelFlowTrigger存在的内存泄漏(取消超时机制)

This commit is contained in:
fengjiayi
2024-09-21 10:06:44 +08:00
parent a1ecd259dd
commit 3537a49784
15 changed files with 624 additions and 304 deletions

View File

@@ -8,7 +8,6 @@ namespace Serein.Library.Api
{
IFlowEnvironment FlowEnvironment { get; }
ISereinIOC SereinIoc { get; }
NodeRunCts NodeRunCts { get; set; }
Task CreateTimingTask(Action action, int time = 100, int count = -1);
}
}

View File

@@ -25,6 +25,12 @@ namespace Serein.Library.Api
/// 获取或创建并注入目标类型
/// </summary>
object GetOrRegisterInstantiate(Type type);
object Get(Type type);
T Get<T>(string name);
object Get(string name);
void CustomRegisterInstance(string name, object instance, bool needInjectProperty = true);
/// <summary>
/// 创建目标类型的对象, 并注入依赖项

View File

@@ -37,12 +37,20 @@ namespace Serein.Library.Utils
try
{
await Task.Delay(outTime, cts.Token);
await channel.Writer.WriteAsync(CancelType.Overtime);
if(!cts.Token.IsCancellationRequested)
{
await channel.Writer.WriteAsync(CancelType.Overtime);
}
}
catch (OperationCanceledException)
{
// 超时任务被取消
}
finally
{
cts?.Dispose();
}
}, cts.Token);
// 等待信号传入(超时或手动触发)

View File

@@ -34,8 +34,11 @@ namespace Serein.Library.NodeFlow.Tool
// 使用并发字典管理每个枚举信号对应的 Channel
private readonly ConcurrentDictionary<TSignal, Channel<TriggerData>> _channels = new ConcurrentDictionary<TSignal, Channel<TriggerData>>();
// 到期后自动触发。短时间内触发频率过高的情况下,请将 outTime 设置位短一些的时间,因为如果超时等待时间过长,会导致非预期的“托管内存泄露”。
/// <summary>
/// 创建信号并指定超时时间,到期后自动触发(异步方法)
/// 创建信号并指定超时时间的Channel.
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <param name="outTime">超时时间</param>
@@ -43,29 +46,39 @@ namespace Serein.Library.NodeFlow.Tool
public async Task<TriggerData> CreateChannelWithTimeoutAsync<TResult>(TSignal signal, TimeSpan outTime, TResult outValue)
{
var channel = GetOrCreateChannel(signal);
var cts = new CancellationTokenSource();
// 异步任务:超时后自动触发信号
_ = Task.Run(async () =>
{
try
{
await Task.Delay(outTime, cts.Token);
TriggerData triggerData = new TriggerData()
{
Value = outValue,
Type = TriggerType.Overtime,
};
await channel.Writer.WriteAsync(triggerData);
}
catch (OperationCanceledException)
{
// 超时任务被取消
}
}, cts.Token);
//var cts = new CancellationTokenSource();
//// 异步任务:超时后自动触发信号
//_ = Task.Run(async () =>
//{
// try
// {
// await Task.Delay(outTime, cts.Token);
// if(!cts.IsCancellationRequested) // 如果还没有被取消
// {
// TriggerData triggerData = new TriggerData()
// {
// Value = outValue,
// Type = TriggerType.Overtime,
// };
// await channel.Writer.WriteAsync(triggerData);
// }
// }
// catch (OperationCanceledException)
// {
// // 超时任务被取消
// }
// finally
// {
// cts?.Cancel();
// cts?.Dispose(); // 确保 cts 被释放
// }
//}, cts.Token);
// 等待信号传入(超时或手动触发)
var result = await channel.Reader.ReadAsync();
//cts?.Cancel();
//cts?.Dispose();
return result;
}

View File

@@ -1,4 +1,5 @@
using Serein.Library.Api;
using Newtonsoft.Json.Linq;
using Serein.Library.Api;
using Serein.Library.Attributes;
using Serein.Library.Web;
using System;
@@ -6,6 +7,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
namespace Serein.Library.Utils
{
@@ -88,8 +90,7 @@ namespace Serein.Library.Utils
public ISereinIOC Register<TService, TImplementation>(params object[] parameters)
where TImplementation : TService
{
var typeFullName = typeof(TService).FullName;
RegisterType(typeFullName, typeof(TImplementation));
RegisterType(typeof(TService).FullName, typeof(TImplementation));
return this;
}
#endregion
@@ -140,6 +141,57 @@ namespace Serein.Library.Utils
return (T)GetOrRegisterInstantiate(typeof(T));
}
public void CustomRegisterInstance(string name,object instance, bool needInjectProperty = true)
{
// 不存在时才允许创建
if (!_dependencies.ContainsKey(name))
{
_dependencies.TryAdd(name, instance);
}
if (needInjectProperty)
{
InjectDependencies(instance); // 注入实例需要的依赖项
}
// 检查是否存在其它实例
if (_unfinishedDependencies.TryGetValue(name, out var unfinishedPropertyList))
{
foreach ((object obj, PropertyInfo property) in unfinishedPropertyList)
{
property.SetValue(obj, instance); //注入依赖项
}
if (_unfinishedDependencies.TryRemove(name, out unfinishedPropertyList))
{
unfinishedPropertyList.Clear();
}
}
}
public object Get(Type type)
{
return Get(type.FullName);
}
public T Get<T>(string name)
{
return (T)Get(name);
}
public object Get(string name)
{
object value;
if (!_dependencies.TryGetValue(name, out value))
{
value = null;
}
return value;
}
/// <summary>
/// 根据类型生成对应的实例并注入其中的依赖项类型信息不登记到IOC容器中,类型创建后自动注入其它需要此类型的对象
/// </summary>