基于ECS的工作流编排框架

引言

在现代复杂应用系统中,工作流编排、配置动态管理和异步任务处理往往是核心挑战。OrchestrationFramework 是一个基于 Entity-Component-System(ECS) 架构设计的 C# 框架,它提供了一套完整的工作流生命周期管理、节点与工作流关联、配置自动刷新以及任务并发控制的解决方案。本文将聚焦于框架的工作流相关模块,介绍其核心数据模型、存储管理器、配置自动更新机制以及辅助的任务处理能力,帮助您快速理解如何在项目中应用该框架。

一、核心数据模型

框架定义了简洁而强大的数据模型来抽象工作流及其与节点的关系。

  1. WorkflowReference
    csharp
    public class WorkflowReference where TWorkflow : class
    {
    public string WorkflowId { get; set; }
    public TWorkflow Workflow { get; set; }
    public HashSet NodeIds { get; set; } = new();
    }
    WorkflowId:工作流的唯一标识。

Workflow:实际的工作流对象,可以是任何类(如配置对象、流程定义等)。

NodeIds:与该工作流关联的所有节点 ID 集合。节点可以是任何需要与工作流绑定的实体(如 UI 元素、游戏对象、业务步骤等)。

  1. INodeConfigExtractor
    csharp
    public interface INodeConfigExtractor where TWorkflow : class
    {
    string GetWorkflowName(TWorkflow workflow);
    IEnumerable GetNodeIds(TWorkflow workflow);
    string GetNodeId(TWorkflow workflow, string nodeKey = null);
    }
    该接口定义了如何从工作流对象中提取节点信息。用户需要根据实际工作流结构实现它,框架依赖此接口来建立工作流与节点的关联。

二、工作流存储管理器

IWorkflowStorageManager 是框架的核心服务接口,定义了工作流存储与查询的操作。

主要功能

注册或更新工作流:string RegisterOrUpdateWorkflow(TWorkflow workflow) 返回工作流 ID。

获取工作流:TWorkflow GetWorkflow(string workflowId)

节点关联查询:

List FindWorkflowsByNode(string nodeId):根据节点 ID 查找所有关联的工作流。

string GetWorkflowIdForNode(string nodeId):获取节点所在的首个工作流 ID(简化版)。

bool IsNodeInAnyWorkflow(string nodeId)

获取所有工作流 ID:List GetAllWorkflowIds()

获取工作流引用:WorkflowReference GetWorkflowReference(string workflowId) 返回包含节点 ID 集合的完整引用。

移除工作流:void RemoveWorkflow(string workflowId)

观察者机制:

void RegisterObserver(string workflowId, Action callback):订阅工作流更新。

void UnregisterObserver(...)

void RegisterRemovalObserver(string workflowId, Action callback):订阅工作流移除事件。

基于ECS的实现:GenericWorkflowStorageManager

框架提供了默认实现 GenericWorkflowStorageManager,它内部利用 ECS 世界来高效管理实体和组件。该实现的主要特点:

后台线程驱动:启动独立线程运行 ECS 更新循环,所有命令通过线程安全的队列提交,保证数据一致性。

读写锁保护:查询操作使用读写锁,支持高并发读取。

工作流-节点映射:通过两个 ECS 实体(工作流实体、节点实体)及组件关系,实现多对多映射,并通过上下文数据维护快速索引。

观察者通知:当工作流组件变化或实体销毁时,触发内部事件,进而调用注册的回调。回调可选择在捕获的同步上下文(如 UI 线程)上执行,便于与界面集成。

使用示例

csharp

// 定义工作流类

public class MyWorkflow { public string Name; public List Steps; }

// 实现节点提取器

public class MyExtractor : INodeConfigExtractor

{

public IEnumerable GetNodeIds(MyWorkflow workflow) => workflow.Steps;

public string GetWorkflowName(MyWorkflow workflow) => workflow.Name;

public string GetNodeId(MyWorkflow workflow, string nodeKey = null) => nodeKey ?? workflow.Steps.FirstOrDefault();

}

// 创建存储管理器

var storage = new GenericWorkflowStorageManager(new MyExtractor());

// 注册工作流

var workflow = new MyWorkflow { Name = "流程A", Steps = new List { "步骤1", "步骤2" } };

string wfId = storage.RegisterOrUpdateWorkflow(workflow);

// 通过节点查询

var wfIds = storage.FindWorkflowsByNode("步骤1");

// 订阅更新

storage.RegisterObserver(wfId, wf => Console.WriteLine($"工作流更新:{wf.Name}"));

// 获取引用

var ref = storage.GetWorkflowReference(wfId);

Console.WriteLine($"工作流 {ref.WorkflowId} 包含节点:{string.Join(",", ref.NodeIds)}");

三、工作流与节点的多对多关系管理

框架通过 ECS 组件实现了工作流与节点的灵活关联:

每个工作流被建模为一个工作流实体,带有 WorkflowComponent(存储工作流 ID、对象、节点 ID 集合)。

每个节点被建模为一个节点实体,带有 NodeComponent(存储节点 ID)和 WorkflowRefComponent(指向所属的工作流实体)。

上下文数据 NodeEntityMapData 维护节点 ID 到节点实体列表的映射,实现快速反向查询。

这种设计支持:

一个工作流可关联多个节点。

一个节点可属于多个工作流(多对多)。

节点实体和工作流实体独立生命周期,移除工作流时自动销毁关联的节点实体。

四、自动刷新的配置基类:GenericWorkflowConfig

在实际应用中,我们经常需要将工作流数据映射到具体的配置对象,并在工作流变化时自动更新配置。GenericWorkflowConfig 抽象类正是为此设计。

工作原理

每个配置实例与一个配置键(通常是节点 ID)绑定。

构造时,自动根据配置键查找对应的工作流 ID,并注册工作流更新观察者。

当工作流发生变化时,OnWorkflowUpdated 被触发,调用 Refresh() 方法重新从工作流中提取数据并更新配置。

子类需实现:

UpdateFromWorkflow(TWorkflow workflow):从工作流更新配置属性。

ResetToDefaults():当工作流不存在或无效时重置为默认值。

IsConfigValidForWorkflow(TWorkflow workflow):验证工作流是否适用于当前配置。

使用示例

csharp

public class MyConfig : GenericWorkflowConfig

{

public string WorkflowName { get; private set; }

public List Steps { get; private set; } = new();

复制代码
public MyConfig(string configKey, IWorkflowStorageManager<MyWorkflow> storage, string workflowId = null)
    : base(configKey, storage, workflowId) { }

protected override void UpdateFromWorkflow(MyWorkflow workflow)
{
    WorkflowName = workflow.Name;
    Steps = workflow.Steps.ToList();
}

protected override void ResetToDefaults()
{
    WorkflowName = "默认";
    Steps.Clear();
}

protected override bool IsConfigValidForWorkflow(MyWorkflow workflow) => workflow != null;

}

// 在代码中使用

var config = new MyConfig("步骤1", storage);

// 当工作流更新时,config 自动刷新

五、配置管理器:GenericConfigManager

为了集中管理多个配置实例,框架提供了 GenericConfigManager<TConfig, TWorkflow>。它内部维护一个线程安全的字典缓存,通过工厂方法创建配置实例。

GetOrCreateConfig:根据键获取或创建配置,可传入初始工作流以便首次注册。

TryGetConfig:尝试获取已有配置。

RemoveConfig:移除并释放配置。

ClearAllConfigs:清空所有配置。

该管理器简化了配置的生命周期管理,适用于动态创建和销毁配置的场景。

六、辅助模块:任务处理器与消息队列

虽然这两个模块不直接属于工作流核心,但它们常与工作流结合使用,例如异步处理工作流任务、在工作流之间传递消息等。

  1. TaskProcessor
    通用异步任务处理器,支持按键串行处理任务,防止并发冲突。

SubmitTask:提交任务,同一键的任务会排队执行。

递归深度检测:防止无限递归。

后台处理循环:独立任务不断从阻塞队列中取出任务执行。

适用场景:按用户 ID 串行处理工作流任务、避免资源竞争。

  1. 消息队列
    框架提供 SimpleMessageQueue(FIFO)和 PriorityMessageQueue(优先级队列),均支持:

暂停/恢复

终止当前处理

超时获取

事件通知

在工作流系统中,可用作工作流引擎的事件总线或任务调度队列。

七、总结

OrchestrationFramework 的工作流部分提供了一套完整、高性能且易于扩展的解决方案。其核心优势包括:

解耦与灵活性:通过接口和抽象类,存储管理器、节点提取器均可自定义。

高效查询:ECS 内部实现确保节点与工作流的关联查询快速且内存友好。

自动更新:观察者机制使得配置对象能实时响应工作流变化,无需轮询。

多对多关系:支持节点与工作流的灵活映射,适应复杂业务。

并发安全:读写锁、命令队列、后台线程等设计保证了多线程环境下的稳定性。

无论是构建工作流驱动的配置系统、多租户任务处理平台,还是需要动态响应的业务应用,该框架都能提供坚实的支撑。希望本文能帮助您快速掌握其核心用法,并在实际项目中发挥价值。

csharp 复制代码
namespace OrchestrationFramework
{
    #region 核心数据模型(保持原样)
    public class WorkflowReference<TWorkflow> where TWorkflow : class
    {
        public string WorkflowId { get; set; }
        public TWorkflow Workflow { get; set; }
        public HashSet<string> NodeIds { get; set; } = new();
    }
    #endregion

    #region 接口定义(保持原样)
    public interface IWorkflowStorageManager<TWorkflow> where TWorkflow : class
    {
        string RegisterOrUpdateWorkflow(TWorkflow workflow);
        TWorkflow GetWorkflow(string workflowId);
        List<string> FindWorkflowsByNode(string nodeId);
        string GetWorkflowIdForNode(string nodeId);
        bool IsNodeInAnyWorkflow(string nodeId);
        List<string> GetAllWorkflowIds();
        WorkflowReference<TWorkflow> GetWorkflowReference(string workflowId);
        void RemoveWorkflow(string workflowId);
        void RegisterObserver(string workflowId, Action<TWorkflow> callback);
        void UnregisterObserver(string workflowId, Action<TWorkflow> callback);
        void RegisterRemovalObserver(string workflowId, Action<string> callback);
    }

    public interface INodeConfigExtractor<TWorkflow> where TWorkflow : class
    {
        string GetWorkflowName(TWorkflow workflow);
        IEnumerable<string> GetNodeIds(TWorkflow workflow);
        string GetNodeId(TWorkflow workflow, string nodeKey = null);
    }
    #endregion

    #region ECS 内部组件(适配新框架)
    namespace Internal
    {
        using ContextManagement;
        using ECS.Core;
        using System;
        using System.Collections.Concurrent;
        using System.Collections.Generic;
        using System.Linq;
        using System.Threading;
        using System.Threading.Tasks;

        // 工作流实体组件
        internal struct WorkflowComponent<TWorkflow> : IComponent where TWorkflow : class
        {
            public string WorkflowId;
            public TWorkflow Workflow;
            public HashSet<string> NodeIds;
        }

        // 节点实体组件
        internal struct NodeComponent : IComponent
        {
            public string NodeId;
        }

        // 节点指向所属工作流的引用组件
        internal struct WorkflowRefComponent : IComponent
        {
            public Entity WorkflowEntity;
        }

        // 上下文数据:节点ID到节点实体列表的映射(支持多对多)
        internal class NodeEntityMapData : DirtyContextData
        {
            // 使用普通 Dictionary 并在读写锁保护下访问
            public Dictionary<string, List<Entity>> Map { get; } = new();
        }

        // 上下文数据:工作流ID到观察者列表
        internal class WorkflowObserversData<TWorkflow> : DirtyContextData where TWorkflow : class
        {
            public ConcurrentDictionary<string, List<Action<TWorkflow>>> Observers { get; } = new();
            public ConcurrentDictionary<string, List<Action<string>>> RemovalObservers { get; } = new();
        }

        // 命令类型
        internal enum WorkflowCommandType
        {
            RegisterOrUpdate,
            Remove
        }

        internal class WorkflowCommand<TWorkflow> where TWorkflow : class
        {
            public WorkflowCommandType Type { get; set; }
            public TWorkflow Workflow { get; set; }
            public string WorkflowId { get; set; }
            public TaskCompletionSource<string> Tcs { get; set; }
            public TaskCompletionSource<bool> RemoveTcs { get; set; }
        }

        // 工作流注册系统(适配新框架)
        internal class WorkflowRegistrationSystem<TWorkflow> : SystemBase where TWorkflow : class
        {
            private readonly ConcurrentQueue<WorkflowCommand<TWorkflow>> _commandQueue = new();
            private NodeEntityMapData _nodeMap;
            private WorkflowObserversData<TWorkflow> _observersData;
            private readonly INodeConfigExtractor<TWorkflow> _nodeExtractor;
            private readonly Func<TWorkflow, string> _workflowIdGenerator;
            private readonly ReaderWriterLockSlim _lock;

            public WorkflowRegistrationSystem(
                INodeConfigExtractor<TWorkflow> nodeExtractor,
                Func<TWorkflow, string> workflowIdGenerator,
                ReaderWriterLockSlim rwLock)
            {
                _nodeExtractor = nodeExtractor;
                _workflowIdGenerator = workflowIdGenerator;
                _lock = rwLock;
            }

            public override void Initialize(EntityManager entityManager)
            {
                base.Initialize(entityManager);
                var context = entityManager.GetOrCreateContext();

                _lock.EnterWriteLock();
                try
                {
                    if (!context.TryGetData<NodeEntityMapData>(out _nodeMap))
                    {
                        _nodeMap = new NodeEntityMapData();
                        context.SetData(_nodeMap);
                    }
                    if (!context.TryGetData<WorkflowObserversData<TWorkflow>>(out _observersData))
                    {
                        _observersData = new WorkflowObserversData<TWorkflow>();
                        context.SetData(_observersData);
                    }
                }
                finally
                {
                    _lock.ExitWriteLock();
                }
            }

            public void SubmitCommand(WorkflowCommand<TWorkflow> command) => _commandQueue.Enqueue(command);

            public override void Update(float deltaTime)
            {
                while (_commandQueue.TryDequeue(out var cmd))
                {
                    _lock.EnterWriteLock();
                    try
                    {
                        switch (cmd.Type)
                        {
                            case WorkflowCommandType.RegisterOrUpdate:
                                ExecuteRegisterOrUpdate(cmd.Workflow, cmd.Tcs);
                                break;
                            case WorkflowCommandType.Remove:
                                ExecuteRemove(cmd.WorkflowId, cmd.RemoveTcs);
                                break;
                        }
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }
                }
            }

            private void ExecuteRegisterOrUpdate(TWorkflow workflow, TaskCompletionSource<string> tcs)
            {
                try
                {
                    var workflowId = _workflowIdGenerator(workflow);
                    var newNodeIds = new HashSet<string>(_nodeExtractor.GetNodeIds(workflow) ?? Enumerable.Empty<string>());

                    var workflowEntity = FindWorkflowEntity(workflowId);
                    if (workflowEntity == Entity.Invalid)
                    {
                        workflowEntity = EntityManager.CreateEntity();
                        EntityManager.AddComponent(workflowEntity, new WorkflowComponent<TWorkflow>
                        {
                            WorkflowId = workflowId,
                            Workflow = workflow,
                            NodeIds = newNodeIds
                        });
                        SynchronizeNodeEntities(workflowEntity, null, newNodeIds);
                    }
                    else
                    {
                        // 获取副本,修改后写回
                        var wfComp = EntityManager.GetComponent<WorkflowComponent<TWorkflow>>(workflowEntity);
                        var oldNodeIds = wfComp.NodeIds ?? new HashSet<string>();
                        wfComp.Workflow = workflow;
                        wfComp.NodeIds = newNodeIds;
                        EntityManager.SetComponent(workflowEntity, wfComp);
                        SynchronizeNodeEntities(workflowEntity, oldNodeIds, newNodeIds);
                    }

                    tcs.SetResult(workflowId);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            }

            private void ExecuteRemove(string workflowId, TaskCompletionSource<bool> tcs)
            {
                try
                {
                    var workflowEntity = FindWorkflowEntity(workflowId);
                    if (workflowEntity == Entity.Invalid)
                    {
                        tcs.SetResult(false);
                        return;
                    }

                    var wfComp = EntityManager.GetComponent<WorkflowComponent<TWorkflow>>(workflowEntity);
                    var nodeIds = wfComp.NodeIds ?? new HashSet<string>();

                    foreach (var nodeId in nodeIds)
                    {
                        if (_nodeMap.Map.TryGetValue(nodeId, out var nodeEntities))
                        {
                            // 找到属于当前工作流的节点实体并移除
                            var toRemove = nodeEntities.FirstOrDefault(e =>
                                EntityManager.TryGetComponent<WorkflowRefComponent>(e, out var refComp) &&
                                refComp.WorkflowEntity == workflowEntity);
                            if (toRemove != Entity.Invalid)
                            {
                                nodeEntities.Remove(toRemove);
                                EntityManager.DestroyEntity(toRemove);
                                if (nodeEntities.Count == 0)
                                    _nodeMap.Map.Remove(nodeId);
                            }
                        }
                    }

                    EntityManager.DestroyEntity(workflowEntity);
                    tcs.SetResult(true);
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            }

            // 同步节点实体:支持多对多
            private void SynchronizeNodeEntities(Entity workflowEntity, HashSet<string> oldNodeIds, HashSet<string> newNodeIds)
            {
                var toRemove = oldNodeIds?.Except(newNodeIds).ToList() ?? new List<string>();
                var toAdd = newNodeIds.Except(oldNodeIds ?? Enumerable.Empty<string>()).ToList();

                foreach (var nodeId in toRemove)
                {
                    if (_nodeMap.Map.TryGetValue(nodeId, out var nodeEntities))
                    {
                        var toDelete = nodeEntities.FirstOrDefault(e =>
                            EntityManager.TryGetComponent<WorkflowRefComponent>(e, out var refComp) &&
                            refComp.WorkflowEntity == workflowEntity);
                        if (toDelete != Entity.Invalid)
                        {
                            nodeEntities.Remove(toDelete);
                            EntityManager.DestroyEntity(toDelete);
                            if (nodeEntities.Count == 0)
                                _nodeMap.Map.Remove(nodeId);
                        }
                    }
                }

                foreach (var nodeId in toAdd)
                {
                    var nodeEntity = EntityManager.CreateEntity();
                    EntityManager.AddComponent(nodeEntity, new NodeComponent { NodeId = nodeId });
                    EntityManager.AddComponent(nodeEntity, new WorkflowRefComponent { WorkflowEntity = workflowEntity });

                    if (!_nodeMap.Map.TryGetValue(nodeId, out var nodeEntities))
                    {
                        nodeEntities = new List<Entity>();
                        _nodeMap.Map[nodeId] = nodeEntities;
                    }
                    nodeEntities.Add(nodeEntity);
                }
            }

            private Entity FindWorkflowEntity(string workflowId)
            {
                var query = new EntityQuery(EntityManager).WithComponent<WorkflowComponent<TWorkflow>>();
                foreach (var entity in query.Execute())
                {
                    var comp = EntityManager.GetComponent<WorkflowComponent<TWorkflow>>(entity);
                    if (comp.WorkflowId == workflowId)
                        return entity;
                }
                return Entity.Invalid;
            }
        }

        // 工作流通知系统(适配新框架)
        internal class WorkflowNotificationSystem<TWorkflow> : SystemBase where TWorkflow : class
        {
            private WorkflowObserversData<TWorkflow> _observersData;
            private readonly HashSet<string> _changedWorkflowIds = new();
            private readonly object _lock = new();
            private readonly ReaderWriterLockSlim _rwLock;
            private readonly SynchronizationContext _syncContext;
            private readonly Action _notifyUpdate;

            public WorkflowNotificationSystem(
                ReaderWriterLockSlim rwLock,
                SynchronizationContext syncContext,
                Action notifyUpdate)
            {
                _rwLock = rwLock;
                _syncContext = syncContext;
                _notifyUpdate = notifyUpdate;
            }

            public override void Initialize(EntityManager entityManager)
            {
                base.Initialize(entityManager);
                var context = entityManager.GetOrCreateContext();

                _rwLock.EnterWriteLock();
                try
                {
                    if (!context.TryGetData(out _observersData))
                    {
                        _observersData = new WorkflowObserversData<TWorkflow>();
                        context.SetData(_observersData);
                    }
                }
                finally
                {
                    _rwLock.ExitWriteLock();
                }

                EntityManager.ComponentAdded += OnComponentChanged;
                EntityManager.ComponentRemoved += OnComponentChanged;
                EntityManager.EntityDestroyed += OnEntityDestroyed;
            }

            private void OnComponentChanged(Entity entity, Type componentType)
            {
                if (componentType == typeof(WorkflowComponent<TWorkflow>))
                {
                    // 调用时已在写锁内,无需再次获取锁
                    if (EntityManager.TryGetComponent<WorkflowComponent<TWorkflow>>(entity, out var wfComp))
                    {
                        lock (_lock) _changedWorkflowIds.Add(wfComp.WorkflowId);
                        _notifyUpdate();
                    }
                }
            }

            private void OnEntityDestroyed(Entity entity)
            {
                // 调用时已在写锁内
                if (EntityManager.TryGetComponent<WorkflowComponent<TWorkflow>>(entity, out var wfComp))
                {
                    TriggerRemovalCallbacks(wfComp.WorkflowId);
                }
            }

            private void TriggerRemovalCallbacks(string workflowId)
            {
                if (_observersData.RemovalObservers.TryGetValue(workflowId, out var callbacks))
                {
                    List<Action<string>> snapshot;
                    lock (callbacks) snapshot = callbacks.ToList(); // 加锁获取快照
                    foreach (var cb in snapshot)
                    {
                        ExecuteCallback(() => cb(workflowId));
                    }
                }
            }

            public override void Update(float deltaTime)
            {
                HashSet<string> toNotify;
                lock (_lock)
                {
                    toNotify = new HashSet<string>(_changedWorkflowIds);
                    _changedWorkflowIds.Clear();
                }

                foreach (var wfId in toNotify)
                {
                    if (_observersData.Observers.TryGetValue(wfId, out var callbacks))
                    {
                        TWorkflow workflow = FindWorkflowById(wfId);
                        if (workflow != null)
                        {
                            List<Action<TWorkflow>> snapshot;
                            lock (callbacks) snapshot = callbacks.ToList(); // 加锁获取快照
                            foreach (var cb in snapshot)
                            {
                                ExecuteCallback(() => cb(workflow));
                            }
                        }
                    }
                }
            }

            private void ExecuteCallback(Action action)
            {
                if (_syncContext != null)
                    _syncContext.Post(_ => action(), null);
                else
                    action();
            }

            private TWorkflow FindWorkflowById(string workflowId)
            {
                _rwLock.EnterReadLock();
                try
                {
                    var query = new EntityQuery(EntityManager).WithComponent<WorkflowComponent<TWorkflow>>();
                    foreach (var entity in query.Execute())
                    {
                        var comp = EntityManager.GetComponent<WorkflowComponent<TWorkflow>>(entity);
                        if (comp.WorkflowId == workflowId)
                            return comp.Workflow;
                    }
                    return null;
                }
                finally
                {
                    _rwLock.ExitReadLock();
                }
            }

            public override void Dispose()
            {
                EntityManager.ComponentAdded -= OnComponentChanged;
                EntityManager.ComponentRemoved -= OnComponentChanged;
                EntityManager.EntityDestroyed -= OnEntityDestroyed;
                base.Dispose();
            }
        }
    }
    #endregion

    #region 重构后的 GenericWorkflowStorageManager(基于ECS,已适配新框架)
    public class GenericWorkflowStorageManager<TWorkflow> : IWorkflowStorageManager<TWorkflow> where TWorkflow : class
    {
        private readonly Internal.WorkflowRegistrationSystem<TWorkflow> _registrationSystem;
        private readonly Internal.WorkflowNotificationSystem<TWorkflow> _notificationSystem;
        private readonly EcsWorld _world;
        private readonly INodeConfigExtractor<TWorkflow> _nodeExtractor;
        private readonly Func<TWorkflow, string> _workflowIdGenerator;
        private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
        private readonly CancellationTokenSource _cts = new CancellationTokenSource();
        private readonly AutoResetEvent _updateEvent = new AutoResetEvent(false);
        private readonly Thread _backgroundThread;
        private readonly SynchronizationContext _syncContext;
        private volatile bool _disposed;
        private readonly IContext _context; // 缓存上下文

        public GenericWorkflowStorageManager(
            INodeConfigExtractor<TWorkflow> nodeExtractor,
            Func<TWorkflow, string> workflowIdGenerator = null)
        {
            _nodeExtractor = nodeExtractor ?? throw new ArgumentNullException(nameof(nodeExtractor));
            _workflowIdGenerator = workflowIdGenerator ?? DefaultWorkflowIdGenerator;

            _syncContext = SynchronizationContext.Current; // 捕获调用线程的同步上下文(用于回调)
            _world = new EcsWorld();
            _context = _world.EntityManager.GetOrCreateContext(); // 获取并缓存上下文

            _registrationSystem = _world.SystemManager.RegisterSystem(
                new Internal.WorkflowRegistrationSystem<TWorkflow>(_nodeExtractor, _workflowIdGenerator, _rwLock));
            _notificationSystem = _world.SystemManager.RegisterSystem(
                new Internal.WorkflowNotificationSystem<TWorkflow>(_rwLock, _syncContext, () => _updateEvent.Set()));

            _backgroundThread = new Thread(RunWorldUpdateLoop) { IsBackground = true };
            _backgroundThread.Start();
        }

        // 默认 ID 生成器:基于工作流类型名称和 GUID,确保唯一性
        private static string DefaultWorkflowIdGenerator(TWorkflow workflow)
        {
            var workflowName = workflow?.GetType().Name ?? "unknown";
            using var md5 = System.Security.Cryptography.MD5.Create();
            var hashBytes = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes($"workflow_{workflowName}_{Guid.NewGuid()}"));
            return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
        }

        private void RunWorldUpdateLoop()
        {
            var token = _cts.Token;
            var waitHandles = new WaitHandle[] { _updateEvent, token.WaitHandle };
            while (!token.IsCancellationRequested)
            {
                try
                {
                    var index = WaitHandle.WaitAny(waitHandles);
                    if (index == 1) break; // 取消信号

                    _world.Update(0); // 执行 ECS 更新
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"World update error: {ex}");
                }
            }
        }

        public string RegisterOrUpdateWorkflow(TWorkflow workflow)
        {
            if (workflow == null) throw new ArgumentNullException(nameof(workflow));
            var tcs = new TaskCompletionSource<string>();
            var cmd = new Internal.WorkflowCommand<TWorkflow>
            {
                Type = Internal.WorkflowCommandType.RegisterOrUpdate,
                Workflow = workflow,
                Tcs = tcs
            };
            _registrationSystem.SubmitCommand(cmd);
            _updateEvent.Set();
            return tcs.Task.GetAwaiter().GetResult();
        }

        public TWorkflow GetWorkflow(string workflowId)
        {
            ValidateWorkflowId(workflowId);
            _rwLock.EnterReadLock();
            try
            {
                var query = new EntityQuery(_world.EntityManager).WithComponent<Internal.WorkflowComponent<TWorkflow>>();
                foreach (var entity in query.Execute())
                {
                    var comp = _world.EntityManager.GetComponent<Internal.WorkflowComponent<TWorkflow>>(entity);
                    if (comp.WorkflowId == workflowId)
                        return comp.Workflow;
                }
                return null;
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public IReadOnlyDictionary<string, WorkflowReference<TWorkflow>> GetReferences()
        {
            _rwLock.EnterReadLock();
            try
            {
                var dict = new Dictionary<string, WorkflowReference<TWorkflow>>();
                var query = new EntityQuery(_world.EntityManager).WithComponent<Internal.WorkflowComponent<TWorkflow>>();
                foreach (var entity in query.Execute())
                {
                    var comp = _world.EntityManager.GetComponent<Internal.WorkflowComponent<TWorkflow>>(entity);
                    var reference = new WorkflowReference<TWorkflow>
                    {
                        WorkflowId = comp.WorkflowId,
                        Workflow = comp.Workflow,
                        NodeIds = new HashSet<string>(comp.NodeIds ?? new HashSet<string>())
                    };
                    dict[comp.WorkflowId] = reference;
                }
                return dict;
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public List<string> FindWorkflowsByNode(string nodeId)
        {
            ValidateNodeId(nodeId);
            _rwLock.EnterReadLock();
            try
            {
                var result = new List<string>();
                if (_context.TryGetData<Internal.NodeEntityMapData>(out var nodeMap) &&
                    nodeMap.Map.TryGetValue(nodeId, out var nodeEntities))
                {
                    foreach (var nodeEntity in nodeEntities)
                    {
                        if (_world.EntityManager.TryGetComponent<Internal.WorkflowRefComponent>(nodeEntity, out var refComp))
                        {
                            var wfEntity = refComp.WorkflowEntity;
                            if (_world.EntityManager.TryGetComponent<Internal.WorkflowComponent<TWorkflow>>(wfEntity, out var wfComp))
                            {
                                result.Add(wfComp.WorkflowId);
                            }
                        }
                    }
                }
                return result;
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public string GetWorkflowIdForNode(string nodeId) => FindWorkflowsByNode(nodeId).FirstOrDefault();

        public bool IsNodeInAnyWorkflow(string nodeId)
        {
            if (string.IsNullOrEmpty(nodeId)) return false;
            _rwLock.EnterReadLock();
            try
            {
                return _context.TryGetData<Internal.NodeEntityMapData>(out var nodeMap) &&
                       nodeMap.Map.ContainsKey(nodeId);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public List<string> GetAllWorkflowIds()
        {
            _rwLock.EnterReadLock();
            try
            {
                var query = new EntityQuery(_world.EntityManager).WithComponent<Internal.WorkflowComponent<TWorkflow>>();
                return query.Execute()
                    .Select(e => _world.EntityManager.GetComponent<Internal.WorkflowComponent<TWorkflow>>(e).WorkflowId)
                    .ToList();
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public WorkflowReference<TWorkflow> GetWorkflowReference(string workflowId)
        {
            ValidateWorkflowId(workflowId);
            _rwLock.EnterReadLock();
            try
            {
                var workflow = GetWorkflow(workflowId);
                if (workflow == null) return null;

                var query = new EntityQuery(_world.EntityManager).WithComponent<Internal.WorkflowComponent<TWorkflow>>();
                foreach (var entity in query.Execute())
                {
                    var comp = _world.EntityManager.GetComponent<Internal.WorkflowComponent<TWorkflow>>(entity);
                    if (comp.WorkflowId == workflowId)
                    {
                        return new WorkflowReference<TWorkflow>
                        {
                            WorkflowId = workflowId,
                            Workflow = workflow,
                            NodeIds = new HashSet<string>(comp.NodeIds ?? new HashSet<string>())
                        };
                    }
                }
                return null;
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        public void RemoveWorkflow(string workflowId)
        {
            ValidateWorkflowId(workflowId);
            var tcs = new TaskCompletionSource<bool>();
            var cmd = new Internal.WorkflowCommand<TWorkflow>
            {
                Type = Internal.WorkflowCommandType.Remove,
                WorkflowId = workflowId,
                RemoveTcs = tcs
            };
            _registrationSystem.SubmitCommand(cmd);
            _updateEvent.Set();
            tcs.Task.GetAwaiter().GetResult();
        }

        public void RegisterObserver(string workflowId, Action<TWorkflow> callback)
        {
            ValidateRegistrationParameters(workflowId, callback);
            _rwLock.EnterWriteLock();
            try
            {
                if (_context.TryGetData<Internal.WorkflowObserversData<TWorkflow>>(out var observersData))
                {
                    var list = observersData.Observers.GetOrAdd(workflowId, _ => new List<Action<TWorkflow>>());
                    lock (list) if (!list.Contains(callback)) list.Add(callback);
                }
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }
        }

        public void UnregisterObserver(string workflowId, Action<TWorkflow> callback)
        {
            ValidateRegistrationParameters(workflowId, callback);
            _rwLock.EnterWriteLock();
            try
            {
                if (_context.TryGetData<Internal.WorkflowObserversData<TWorkflow>>(out var observersData) &&
                    observersData.Observers.TryGetValue(workflowId, out var list))
                {
                    lock (list) list.Remove(callback);
                }
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }
        }

        public void RegisterRemovalObserver(string workflowId, Action<string> callback)
        {
            ValidateRegistrationParameters(workflowId, callback);
            _rwLock.EnterWriteLock();
            try
            {
                if (_context.TryGetData<Internal.WorkflowObserversData<TWorkflow>>(out var observersData))
                {
                    var list = observersData.RemovalObservers.GetOrAdd(workflowId, _ => new List<Action<string>>());
                    lock (list) if (!list.Contains(callback)) list.Add(callback);
                }
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }
        }

        private static void ValidateWorkflowId(string workflowId)
        {
            if (string.IsNullOrEmpty(workflowId)) throw new ArgumentException("Workflow ID cannot be null or empty", nameof(workflowId));
        }

        private static void ValidateNodeId(string nodeId)
        {
            if (string.IsNullOrEmpty(nodeId)) throw new ArgumentException("Node ID cannot be null or empty", nameof(nodeId));
        }

        private static void ValidateRegistrationParameters<T>(string workflowId, T callback)
        {
            if (string.IsNullOrEmpty(workflowId)) throw new ArgumentException("Workflow ID cannot be null or empty", nameof(workflowId));
            if (callback == null) throw new ArgumentNullException(nameof(callback));
        }

        public void Dispose()
        {
            if (_disposed) return;
            _disposed = true;

            _cts.Cancel();
            _updateEvent.Set();
            if (_backgroundThread.IsAlive)
                _backgroundThread.Join(TimeSpan.FromSeconds(5));

            _rwLock.EnterWriteLock();
            try
            {
                _world.Dispose();
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }

            _cts.Dispose();
            _updateEvent.Dispose();
            _rwLock.Dispose();
        }
    }
    #endregion

    #region 重构后的 GenericWorkflowConfig(基于上下文数据自动刷新,保持不变)
    public abstract class GenericWorkflowConfig<TWorkflow> : IDisposable where TWorkflow : class
    {
        private readonly IWorkflowStorageManager<TWorkflow> _storageManager;
        private bool _isDisposed;
        private Action<TWorkflow> _workflowUpdateCallback;
        private string _workflowId;

        public string ConfigKey { get; }
        public string WorkflowId => _workflowId;

        protected GenericWorkflowConfig(string configKey, IWorkflowStorageManager<TWorkflow> storageManager, string workflowId = null)
        {
            ConfigKey = configKey ?? throw new ArgumentException("ConfigKey cannot be null or empty");
            _storageManager = storageManager ?? throw new ArgumentNullException(nameof(storageManager));
            Initialize(workflowId);
        }

        private void Initialize(string workflowId = null)
        {
            _workflowId = workflowId ?? _storageManager.GetWorkflowIdForNode(ConfigKey);
            _workflowUpdateCallback = OnWorkflowUpdated;

            if (!string.IsNullOrEmpty(_workflowId))
                _storageManager.RegisterObserver(_workflowId, _workflowUpdateCallback);

            Refresh();
        }

        public void Refresh()
        {
            if (_isDisposed) throw new ObjectDisposedException(GetType().Name);

            var workflow = GetWorkflow();
            if (workflow != null && IsConfigValidForWorkflow(workflow))
                UpdateFromWorkflow(workflow);
            else
            {
                ResetToDefaults();
                TryFindNewWorkflow();
            }
        }

        protected TWorkflow GetWorkflow()
        {
            if (!string.IsNullOrEmpty(_workflowId))
                return _storageManager.GetWorkflow(_workflowId);

            return TryFindWorkflowForNode();
        }

        private TWorkflow TryFindWorkflowForNode()
        {
            var workflowIdForNode = _storageManager.GetWorkflowIdForNode(ConfigKey);
            if (!string.IsNullOrEmpty(workflowIdForNode))
            {
                UpdateWorkflowId(workflowIdForNode);
                return _storageManager.GetWorkflow(workflowIdForNode);
            }
            return null;
        }

        protected void TryFindNewWorkflow()
        {
            var newWorkflowId = _storageManager.GetWorkflowIdForNode(ConfigKey);
            if (!string.IsNullOrEmpty(newWorkflowId) && newWorkflowId != _workflowId)
                UpdateWorkflowId(newWorkflowId);
        }

        protected void UpdateWorkflowId(string newWorkflowId)
        {
            if (_isDisposed) throw new ObjectDisposedException(GetType().Name);
            if (string.IsNullOrEmpty(newWorkflowId)) throw new ArgumentException("Workflow ID cannot be null or empty");
            if (newWorkflowId == _workflowId) return;

            if (!string.IsNullOrEmpty(_workflowId))
                _storageManager.UnregisterObserver(_workflowId, _workflowUpdateCallback);

            _workflowId = newWorkflowId;
            _storageManager.RegisterObserver(newWorkflowId, _workflowUpdateCallback);
            Refresh();
        }

        protected virtual void OnWorkflowUpdated(TWorkflow workflow)
        {
            if (_isDisposed) throw new ObjectDisposedException(GetType().Name);
            Refresh();
        }

        protected abstract void UpdateFromWorkflow(TWorkflow workflow);
        protected abstract void ResetToDefaults();
        protected abstract bool IsConfigValidForWorkflow(TWorkflow workflow);

        protected virtual void Dispose(bool disposing)
        {
            if (!_isDisposed)
            {
                if (disposing && !string.IsNullOrEmpty(_workflowId))
                    _storageManager.UnregisterObserver(_workflowId, _workflowUpdateCallback);
                _isDisposed = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    #endregion

    #region 重构后的 GenericConfigManager(使用本地字典,保持不变)
    public class GenericConfigManager<TConfig, TWorkflow> : IDisposable
        where TConfig : class, IDisposable
        where TWorkflow : class
    {
        private readonly Func<string, IWorkflowStorageManager<TWorkflow>, string, TConfig> _configFactory;
        private readonly IWorkflowStorageManager<TWorkflow> _storageManager;
        private readonly ConcurrentDictionary<string, TConfig> _cache = new();
        private bool _isDisposed;

        public IReadOnlyDictionary<string, TConfig> ConfigCache => _cache;
        public int Count => _cache.Count;

        public GenericConfigManager(
            Func<string, IWorkflowStorageManager<TWorkflow>, string, TConfig> configFactory,
            IWorkflowStorageManager<TWorkflow> storageManager)
        {
            _configFactory = configFactory ?? throw new ArgumentNullException(nameof(configFactory));
            _storageManager = storageManager ?? throw new ArgumentNullException(nameof(storageManager));
        }

        public List<TConfig> GetAllConfigs()
        {
            if (_isDisposed) throw new ObjectDisposedException(nameof(GenericConfigManager<TConfig, TWorkflow>));
            return _cache.Values.ToList();
        }

        public TConfig GetOrCreateConfig(string key, TWorkflow workflow = null)
        {
            if (_isDisposed) throw new ObjectDisposedException(nameof(GenericConfigManager<TConfig, TWorkflow>));
            if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key cannot be null or empty", nameof(key));

            return _cache.GetOrAdd(key, k =>
            {
                string workflowId = null;
                if (workflow != null)
                    workflowId = _storageManager.RegisterOrUpdateWorkflow(workflow);

                return _configFactory(k, _storageManager, workflowId);
            });
        }

        public bool TryGetConfig(string key, out TConfig config)
        {
            config = null;
            return !_isDisposed && _cache.TryGetValue(key, out config);
        }

        public void RemoveConfig(string key)
        {
            if (_isDisposed) throw new ObjectDisposedException(nameof(GenericConfigManager<TConfig, TWorkflow>));
            if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key cannot be null or empty");

            if (_cache.TryRemove(key, out var config))
                config?.Dispose();
        }

        public void ClearAllConfigs()
        {
            if (_isDisposed) throw new ObjectDisposedException(nameof(GenericConfigManager<TConfig, TWorkflow>));
            foreach (var key in _cache.Keys.ToArray())
                RemoveConfig(key);
        }

        public void Dispose()
        {
            if (!_isDisposed)
            {
                ClearAllConfigs();
                _isDisposed = true;
            }
        }
    }
    #endregion

    #region 任务处理器模块
    public class TaskProcessor<T> : IDisposable
    {
        private readonly BlockingCollection<T> _workQueue = new();
        private readonly ConcurrentDictionary<string, bool> _processingKeys = new();
        private readonly ConcurrentDictionary<string, int> _recursionDepth = new();
        private readonly CancellationTokenSource _cancellationTokenSource = new();
        private readonly Func<T, Task> _processItemFunc;
        private readonly Func<T, string> _getKeyFunc;
        private readonly int _maxRecursionDepth = 10;

        private Task _processingTask;
        private volatile bool _isDisposed;
        private readonly object _lockObject = new();

        public TaskProcessor(Func<T, Task> processItemFunc, Func<T, string> getKeyFunc)
        {
            _processItemFunc = processItemFunc ?? throw new ArgumentNullException(nameof(processItemFunc));
            _getKeyFunc = getKeyFunc ?? throw new ArgumentNullException(nameof(getKeyFunc));
        }

        public void Start()
        {
            lock (_lockObject)
            {
                if (_processingTask == null || _processingTask.IsCompleted)
                    _processingTask = Task.Run(ProcessLoopAsync);
            }
        }

        private async Task ProcessLoopAsync()
        {
            var token = _cancellationTokenSource.Token;

            while (!token.IsCancellationRequested)
            {
                string key = null;
                try
                {
                    T item;
                    try { item = _workQueue.Take(token); }
                    catch (OperationCanceledException) { break; }

                    key = _getKeyFunc(item);
                    var depth = _recursionDepth.AddOrUpdate(key, 1, (k, v) => v + 1);

                    if (depth > _maxRecursionDepth)
                    {
                        _recursionDepth.TryRemove(key, out _);
                        throw new InvalidOperationException($"Maximum recursion depth ({_maxRecursionDepth}) exceeded for key: {key}");
                    }

                    await ProcessSingleItemAsync(item, token);
                }
                catch (OperationCanceledException) { break; }
                catch (Exception)
                {
                    // 发生异常,延迟后继续循环(深度回退在 finally 中处理)
                    await Task.Delay(100, token);
                }
                finally
                {
                    if (key != null)
                    {
                        if (_recursionDepth.TryGetValue(key, out var currentDepth))
                        {
                            if (currentDepth <= 1)
                                _recursionDepth.TryRemove(key, out _);
                            else
                                _recursionDepth[key] = currentDepth - 1;
                        }
                    }
                }
            }
        }

        private async Task ProcessSingleItemAsync(T item, CancellationToken token)
        {
            var key = _getKeyFunc(item);
            try
            {
                _processingKeys[key] = true;
                await _processItemFunc(item);
            }
            finally { _processingKeys.TryRemove(key, out _); }
        }

        public bool SubmitTask(T item)
        {
            if (item == null) throw new ArgumentNullException(nameof(item));
            if (_isDisposed) throw new ObjectDisposedException(nameof(TaskProcessor<T>));

            var key = _getKeyFunc(item);

            if (_processingKeys.ContainsKey(key))
            {
                Task.Delay(50).ContinueWith(_ =>
                {
                    if (!_isDisposed && !_cancellationTokenSource.IsCancellationRequested)
                        _workQueue.Add(item);
                }, _cancellationTokenSource.Token);
                return true;
            }

            _workQueue.Add(item);
            return true;
        }

        public async Task StopAsync(bool graceful = true)
        {
            _cancellationTokenSource.Cancel();

            if (graceful && _processingTask != null)
            {
                try { await _processingTask; }
                catch (OperationCanceledException) { }
                catch (Exception) { }
            }

            while (_workQueue.Count > 0)
                _workQueue.TryTake(out _);
        }

        public void Dispose()
        {
            if (_isDisposed) return;

            _isDisposed = true;
            _cancellationTokenSource.Cancel();

            try { _processingTask?.Wait(TimeSpan.FromSeconds(5)); }
            catch { }

            _cancellationTokenSource.Dispose();
            _workQueue.Dispose();
        }
    }

    public static class TaskProcessorManager<T>
    {
        private static readonly ConcurrentDictionary<string, TaskProcessor<T>> _processors = new();

        public static TaskProcessor<T> GetOrCreateProcessor(string processorId, Func<T, Task> processItemFunc, Func<T, string> getKeyFunc)
            => _processors.GetOrAdd(processorId, id =>
            {
                var processor = new TaskProcessor<T>(processItemFunc, getKeyFunc);
                processor.Start();
                return processor;
            });

        public static bool TryGetProcessor(string processorId, out TaskProcessor<T> processor)
            => _processors.TryGetValue(processorId, out processor);

        public static async Task StopAllProcessorsAsync()
        {
            var stopTasks = _processors.Values.Select(p => p.StopAsync(true));
            await Task.WhenAll(stopTasks);
            _processors.Clear();
        }

        public static void RemoveProcessor(string processorId)
        {
            if (_processors.TryRemove(processorId, out var processor))
                processor.Dispose();
        }
    }
    #endregion

    #region 消息队列
    public class MessageWrapper<T>
    {
        public Guid Id { get; set; }
        public T Message { get; set; }
        public string Name { get; set; }
        public int Priority { get; set; }
        public DateTime Timestamp { get; set; }
        public TimeSpan Age => DateTime.UtcNow - Timestamp;

        public override string ToString() => $"消息: {Name}, 优先级: {Priority}, 年龄: {Age.TotalSeconds:F1}秒";
    }

    public class FunctionTerminationException : Exception
    {
        public FunctionTerminationException(string message) : base(message) { }
        public FunctionTerminationException(string message, Exception innerException) : base(message, innerException) { }
    }

    public class QueuePausedException : Exception
    {
        public QueuePausedException(string message) : base(message) { }
        public QueuePausedException(string message, Exception innerException) : base(message, innerException) { }
    }

    public abstract class MessageQueueBase<T> : IDisposable
    {
        protected readonly CancellationTokenSource _cts = new CancellationTokenSource();
        protected readonly object _pauseLock = new object();
        protected volatile bool _isStopped, _isPaused, _shouldTerminateCurrent, _disposed;
        protected ManualResetEventSlim _pauseEvent = new ManualResetEventSlim(true);

        public bool IsStopped => _isStopped;
        public bool IsPaused => _isPaused;
        public bool ShouldTerminateCurrent => _shouldTerminateCurrent;
        public abstract int Count { get; }
        public abstract bool IsEmpty { get; }

        public virtual Guid StoreMessage(T message, string name = null, int priority = 0)
        {
            if (_isStopped) throw new InvalidOperationException("队列已停止");

            var wrapper = new MessageWrapper<T>
            {
                Id = Guid.NewGuid(),
                Message = message,
                Name = name ?? $"消息_{DateTime.UtcNow:yyyyMMddHHmmssfff}",
                Priority = priority,
                Timestamp = DateTime.UtcNow
            };

            StoreMessageInternal(wrapper);
            return wrapper.Id;
        }

        public virtual MessageWrapper<T> TryRetrieveMessage()
        {
            CheckQueueState();
            CheckPause();
            return TryRetrieveMessageInternal();
        }

        public virtual MessageWrapper<T> RetrieveMessage(int timeoutMs = -1)
        {
            CheckQueueState();
            return RetrieveMessageInternal(timeoutMs);
        }

        public virtual void Pause()
        {
            lock (_pauseLock)
            {
                if (!_isPaused)
                {
                    _isPaused = true;
                    _pauseEvent.Reset();
                    OnPaused?.Invoke(this, EventArgs.Empty);
                }
            }
        }

        public virtual void Resume()
        {
            lock (_pauseLock)
            {
                if (_isPaused)
                {
                    _isPaused = false;
                    _pauseEvent.Set();
                    OnResumed?.Invoke(this, EventArgs.Empty);
                }
            }
        }

        public virtual void TerminateCurrent()
        {
            _shouldTerminateCurrent = true;
            SignalForTermination();
            OnTerminateRequested?.Invoke(this, EventArgs.Empty);
        }

        public virtual void ResetTermination() => _shouldTerminateCurrent = false;

        public virtual void CheckTermination()
        {
            if (_shouldTerminateCurrent)
            {
                _shouldTerminateCurrent = false;
                throw new FunctionTerminationException("当前函数执行已被终止");
            }
        }

        public abstract void Clear();

        public virtual void Stop()
        {
            _isStopped = true;
            _cts.Cancel();
            _pauseEvent.Set();
        }

        protected void CheckQueueState()
        {
            if (_isStopped) throw new InvalidOperationException("队列已停止");
        }

        protected void CheckPause()
        {
            if (_isPaused) _pauseEvent.Wait();
        }

        protected CancellationToken GetCombinedCancellationToken()
        {
            var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token);
            if (_isPaused) linkedCts.Cancel();
            return linkedCts.Token;
        }

        protected abstract void StoreMessageInternal(MessageWrapper<T> wrapper);
        protected abstract MessageWrapper<T> TryRetrieveMessageInternal();
        protected abstract MessageWrapper<T> RetrieveMessageInternal(int timeoutMs);
        protected abstract void SignalForTermination();

        public event EventHandler OnPaused, OnResumed, OnTerminateRequested;

        public virtual void Dispose()
        {
            if (_disposed) return;

            Stop();
            _cts.Dispose();
            _pauseEvent.Dispose();
            _disposed = true;
        }
    }

    public class SimpleMessageQueue<T> : MessageQueueBase<T>
    {
        private readonly BlockingCollection<MessageWrapper<T>> _queue;
        public override int Count => _queue.Count;
        public override bool IsEmpty => _queue.Count == 0;

        public SimpleMessageQueue(int? capacity = null)
        {
            var boundedCapacity = capacity ?? int.MaxValue;
            _queue = new BlockingCollection<MessageWrapper<T>>(boundedCapacity);
        }

        protected override void StoreMessageInternal(MessageWrapper<T> wrapper)
        {
            try { _queue.Add(wrapper, _cts.Token); }
            catch (OperationCanceledException) { throw new InvalidOperationException("队列操作被取消"); }
        }

        protected override MessageWrapper<T> TryRetrieveMessageInternal() => _queue.TryTake(out var message) ? message : null;

        protected override MessageWrapper<T> RetrieveMessageInternal(int timeoutMs)
        {
            try
            {
                if (timeoutMs >= 0)
                    return _queue.TryTake(out var message, timeoutMs, GetCombinedCancellationToken()) ? message : null;
                else
                {
                    while (!_isStopped)
                    {
                        CheckPause();
                        CheckTermination();
                        if (_queue.TryTake(out var message, 100, _cts.Token))
                            return message;
                    }
                    throw new OperationCanceledException("队列已停止");
                }
            }
            catch (OperationCanceledException)
            {
                if (_isPaused) throw new QueuePausedException("队列已暂停");
                else throw new InvalidOperationException("队列操作被取消");
            }
        }

        public override void Clear() { while (_queue.TryTake(out _)) { } }

        protected override void SignalForTermination() => _pauseEvent.Set();

        public override void Stop()
        {
            base.Stop();
            _queue.CompleteAdding();
        }

        public override void Dispose()
        {
            if (_disposed) return;
            base.Dispose();
            _queue.Dispose();
            _disposed = true;
        }
    }

    public class PriorityMessageQueue<T> : MessageQueueBase<T>
    {
        private readonly ConcurrentDictionary<int, ConcurrentQueue<MessageWrapper<T>>> _queues = new();
        private readonly AutoResetEvent _signal = new AutoResetEvent(false);
        public override int Count => _queues.Sum(q => q.Value.Count);
        public override bool IsEmpty => Count == 0;

        protected override void StoreMessageInternal(MessageWrapper<T> wrapper)
        {
            var queue = _queues.GetOrAdd(wrapper.Priority, _ => new ConcurrentQueue<MessageWrapper<T>>());
            queue.Enqueue(wrapper);
            _signal.Set();
        }

        protected override MessageWrapper<T> TryRetrieveMessageInternal()
        {
            var priorities = _queues.Keys.OrderByDescending(p => p).ToList();

            foreach (var priority in priorities)
            {
                if (_queues.TryGetValue(priority, out var queue) && queue.TryDequeue(out var message))
                {
                    if (queue.IsEmpty) _queues.TryRemove(priority, out _);
                    return message;
                }
            }
            return null;
        }

        protected override MessageWrapper<T> RetrieveMessageInternal(int timeoutMs)
        {
            var startTime = DateTime.UtcNow;

            while (true)
            {
                CheckTermination();
                var message = TryRetrieveMessageInternal();
                if (message != null) return message;

                if (timeoutMs >= 0)
                {
                    var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
                    if (elapsed > timeoutMs) return null;

                    var remaining = (int)(timeoutMs - elapsed);
                    if (remaining <= 0 || !WaitForSignalOrPause(remaining)) return null;
                }
                else if (!WaitForSignalOrPause()) return null;

                if (_cts.Token.IsCancellationRequested) throw new OperationCanceledException("队列操作被取消");
            }
        }

        public override void Clear() => _queues.Clear();

        protected override void SignalForTermination()
        {
            _pauseEvent.Set();
            _signal.Set();
        }

        private bool WaitForSignalOrPause(int timeoutMs = Timeout.Infinite)
        {
            var waitHandles = new WaitHandle[] { _signal, _pauseEvent.WaitHandle };
            try
            {
                var result = WaitHandle.WaitAny(waitHandles, timeoutMs);
                return result == 0 || result == 1;
            }
            catch (AbandonedMutexException) { return false; }
        }

        public override MessageWrapper<T> RetrieveMessage(int timeoutMs = -1)
        {
            CheckQueueState();
            if (_isPaused)
            {
                if (timeoutMs >= 0) { if (!_pauseEvent.Wait(timeoutMs)) return null; }
                else _pauseEvent.Wait();
            }
            return RetrieveMessageInternal(timeoutMs);
        }

        public override MessageWrapper<T> TryRetrieveMessage()
        {
            CheckQueueState();
            if (_isPaused) return null;
            return TryRetrieveMessageInternal();
        }

        public override void Stop()
        {
            base.Stop();
            _signal.Set();
        }

        public override void Dispose()
        {
            if (_disposed) return;
            base.Dispose();
            _signal.Dispose();
            _disposed = true;
        }
    }
    #endregion

}
相关推荐
iAkuya1 小时前
(leetcode)力扣100 74 数组中的第K个最大元素(快速选择\堆)
数据结构·算法·leetcode
云深处@1 小时前
【数据结构】排序
数据结构·算法·排序算法
努力努力再努力wz11 小时前
【Linux网络系列】:TCP 的秩序与策略:揭秘传输层如何从不可靠的网络中构建绝对可靠的通信信道
java·linux·开发语言·数据结构·c++·python·算法
重生之后端学习15 小时前
78. 子集
java·数据结构·算法·职场和发展·深度优先
kronos.荒15 小时前
滑动窗口+哈希表:最小覆盖子串
数据结构·python·散列表
wostcdk15 小时前
筛质数汇总
数据结构·算法
qq_4542450316 小时前
BuildTemplateGraph 函数深度解析:动态节点图构建的架构设计与核心价值
数据结构·c#
qq_4542450317 小时前
SkeletonFlow:基于组合子逻辑与范畴论的数据流处理框架
数据结构·c#
游乐码17 小时前
c#静态类和静态构造函数
开发语言·c#