重写了节点主动中断功能,修改了运行环境持久化注册已有实例的逻辑。

This commit is contained in:
fengjiayi
2024-12-26 22:24:44 +08:00
parent 7a6f8c407b
commit 3a7a8483e8
24 changed files with 428 additions and 563 deletions

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Library.Utils
{
/// <summary>
/// 流程运行中断工具
/// </summary>
public class FlowInterruptTool
{
// 使用并发字典管理每个信号对应的广播列表
private readonly ConcurrentDictionary<string, Subject<bool>> _subscribers = new ConcurrentDictionary<string, Subject<bool>>();
/// <summary>
/// 获取或创建指定信号的 Subject消息广播者
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <returns>对应的 Subject</returns>
private Subject<bool> GetOrCreateSubject(string signal)
{
return _subscribers.GetOrAdd(signal, _ => new Subject<bool>());
}
/// <summary>
/// 订阅指定信号的消息
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <param name="action">订阅者</param>
/// <returns>取消订阅的句柄</returns>
private IDisposable Subscribe(string signal, Action<bool> action)
{
IObserver<bool> observer = new Observer<bool>(action);
var subject = GetOrCreateSubject(signal);
return subject.Subscribe(observer); // 返回取消订阅的句柄
}
/// <summary>
/// 等待触发
/// </summary>
/// <param name="signal"></param>
/// <returns></returns>
public async Task<bool> WaitTriggerAsync(string signal)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
var subscription = Subscribe(signal, taskCompletionSource.SetResult);
var result = await taskCompletionSource.Task;
subscription.Dispose(); // 取消订阅
return result;
}
/// <summary>
/// 手动触发信号,并广播给所有订阅者
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <returns>是否成功触发</returns>
public bool InvokeTrigger(string signal)
{
if (_subscribers.TryGetValue(signal, out var subject))
{
subject.OnNext(true); // 广播给所有订阅者
subject.OnCompleted(); // 通知订阅结束
return true;
}
return false;
}
/// <summary>
/// 取消所有任务
/// </summary>
public void CancelAllTrigger()
{
foreach (var subject in _subscribers.Values)
{
subject.OnCompleted(); // 通知所有订阅者结束
}
_subscribers.Clear();
}
}
}

View File

@@ -14,147 +14,7 @@ namespace Serein.Library.Utils
{
/// <summary>
/// 信号触发器类,带有消息广播功能。
/// 使用枚举作为标记,创建
/// </summary>
public class ValueTaskFlowTrigger<TSignal>
{
// 使用并发字典管理每个信号对应的广播列表
private readonly ConcurrentDictionary<TSignal, Subject<TriggerResult<object>>> _subscribers = new ConcurrentDictionary<TSignal, Subject<TriggerResult<object>>>();
/// <summary>
/// 获取或创建指定信号的 Subject消息广播者
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <returns>对应的 Subject</returns>
private Subject<TriggerResult<object>> GetOrCreateSubject(TSignal signal)
{
return _subscribers.GetOrAdd(signal, _ => new Subject<TriggerResult<object>>());
}
/// <summary>
/// 订阅指定信号的消息
/// </summary>
/// <param name="signal">枚举信号标识符</param>
/// <param name="observer">订阅者</param>
/// <returns>取消订阅的句柄</returns>
private IDisposable Subscribe<TResult>(TSignal signal, Action<TriggerResult<object>> action)
{
IObserver<TriggerResult<object>> observer = new Observer<TriggerResult<object>>(action);
var subject = GetOrCreateSubject(signal);
return subject.Subscribe(observer); // 返回取消订阅的句柄
}
/// <summary>
/// 等待触发器并指定超时的时间
/// </summary>
/// <typeparam name="TResult">返回值类型</typeparam>
/// <param name="signal">等待信号</param>
/// <param name="outTime">超时时间</param>
/// <returns></returns>
public async ValueTask<TriggerResult<TResult>> WaitTriggerWithTimeoutAsync<TResult>(TSignal signal, TimeSpan outTime)
{
var subject = GetOrCreateSubject(signal);
var cts = new CancellationTokenSource();
// 异步任务:超时后自动触发信号
_ = Task.Run(async () =>
{
try
{
await Task.Delay(outTime, cts.Token);
if (!cts.IsCancellationRequested) // 如果还没有被取消
{
var outResult = new TriggerResult<object>()
{
Type = TriggerDescription.Overtime
};
subject.OnNext(outResult); // 广播给所有订阅者
subject.OnCompleted(); // 通知订阅结束
}
}
catch (OperationCanceledException)
{
// 超时任务被取消
}
finally
{
cts?.Dispose(); // 确保 cts 被释放
}
}, cts.Token);
var result = await WaitTriggerAsync<TResult>(signal); // 返回一个可以超时触发的等待任务
return result;
}
/// <summary>
/// 等待触发
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="signal"></param>
/// <returns></returns>
public async ValueTask<TriggerResult<TResult>> WaitTriggerAsync<TResult>(TSignal signal)
{
var taskCompletionSource = new TaskCompletionSource<TriggerResult<object>>();
var subscription = Subscribe<TResult>(signal, taskCompletionSource.SetResult);
var result = await taskCompletionSource.Task;
subscription.Dispose(); // 取消订阅
if (result.Value is TResult data)
{
return new TriggerResult<TResult>()
{
Value = data,
Type = TriggerDescription.External,
};
}
else
{
return new TriggerResult<TResult>()
{
Type = TriggerDescription.TypeInconsistency,
};
}
}
/// <summary>
/// 手动触发信号,并广播给所有订阅者
/// </summary>
/// <typeparam name="TResult">触发类型</typeparam>
/// <param name="signal">枚举信号标识符</param>
/// <param name="value">传递的数据</param>
/// <returns>是否成功触发</returns>
public Task<bool> InvokeTriggerAsync<TResult>(TSignal signal, TResult value)
{
if (_subscribers.TryGetValue(signal, out var subject))
{
var result = new TriggerResult<object>()
{
Type = TriggerDescription.External,
Value = value
};
subject.OnNext(result); // 广播给所有订阅者
subject.OnCompleted(); // 通知订阅结束
return Task.FromResult(true);
}
return Task.FromResult(false);
}
/// <summary>
/// 取消所有任务
/// </summary>
public void CancelAllTrigger()
{
foreach (var subject in _subscribers.Values)
{
subject.OnCompleted(); // 通知所有订阅者结束
}
_subscribers.Clear();
}
}

View File

@@ -23,7 +23,7 @@ namespace Serein.Library.Utils
{
// 使用并发字典管理每个信号对应的广播列表
private readonly ConcurrentDictionary<TSignal, Subject<TriggerResult<object>>> _subscribers = new ConcurrentDictionary<TSignal, Subject<TriggerResult<object>>>();
private readonly TriggerResultPool _triggerResultPool = new TriggerResultPool();
private readonly TriggerResultPool<object> _triggerResultPool = new TriggerResultPool<object>();
/// <summary>
/// 获取或创建指定信号的 Subject消息广播者
/// </summary>

View File

@@ -76,18 +76,18 @@ namespace Serein.Library.Utils
/// 使用 ObjectPool 来复用 TriggerResult 对象
/// </summary>
// 示例 TriggerResult 对象池
public class TriggerResultPool
public class TriggerResultPool<TResult>
{
private readonly ConcurrentExpandingObjectPool<TriggerResult<object>> _objectPool;
private readonly ConcurrentExpandingObjectPool<TriggerResult<TResult>> _objectPool;
public TriggerResultPool(int defaultCapacity = 30)
{
_objectPool = new ConcurrentExpandingObjectPool<TriggerResult<object>>(defaultCapacity);
_objectPool = new ConcurrentExpandingObjectPool<TriggerResult<TResult>>(defaultCapacity);
}
public TriggerResult<object> Get() => _objectPool.Get();
public TriggerResult<TResult> Get() => _objectPool.Get();
public void Return(TriggerResult<object> result) => _objectPool.Return(result);
public void Return(TriggerResult<TResult> result) => _objectPool.Return(result);
}

View File

@@ -107,12 +107,20 @@ namespace Serein.Library.Utils
#region
/// <summary>
/// 指定key值注册一个已经实例化的实例对象
/// 指定key值注册一个已经实例化的实例对象,并持久化储存
/// </summary>
/// <param name="key"></param>
/// <param name="instance"></param>
/// <param name="needInjectProperty"></param>
public bool CustomRegisterInstance(string key, object instance, bool needInjectProperty = true)
public bool RegisterInstance(string key, object instance)
{
return RegisterPersistennceInstance(key, instance);
}
/// <summary>
/// 指定key值注册一个已经实例化的实例对象并持久化储存
/// </summary>
/// <param name="key"></param>
/// <param name="instance"></param>
public bool RegisterPersistennceInstance(string key, object instance)
{
// 不存在时才允许创建
if (_dependencies.ContainsKey(key))
@@ -120,11 +128,11 @@ namespace Serein.Library.Utils
return false;
}
_dependencies.TryAdd(key, instance);
if (needInjectProperty)
{
InjectDependencies(instance); // 注入实例需要的依赖项
}
InjectUnfinishedDependencies(key, instance); // 检查是否存在其它实例需要该类型
//if (needInjectProperty)
//{
// InjectDependencies(instance); // 注入实例需要的依赖项
//}
//InjectUnfinishedDependencies(key, instance); // 检查是否存在其它实例需要该类型
OnIOCMembersChanged?.Invoke(new IOCMembersChangedEventArgs(key, instance));
return true;
}