c#实现基于事件驱动的自动流程控制,包含任务超时,任务执行metric

实现事件驱动模型

这个类实现了事件分发,和队列任务执行,以及成功回调,失败回调和超时处理

复制代码
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

public class EventDrivenTaskQueue : IDisposable
{
    private readonly ConcurrentDictionary<string, Func<object, CancellationToken, Task<object>>> _tasks = new ConcurrentDictionary<string, Func<object, CancellationToken, Task<object>>>();
    private readonly ConcurrentDictionary<string, ManualResetEventSlim> _events = new ConcurrentDictionary<string, ManualResetEventSlim>();
    private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
    private readonly Thread _workerThread;
    private readonly ConcurrentDictionary<string, object> _taskResults = new ConcurrentDictionary<string, object>();
    private readonly ConcurrentDictionary<string, TimeSpan> _taskTimeouts = new ConcurrentDictionary<string, TimeSpan>();
    private readonly ConcurrentQueue<string> _taskQueue = new ConcurrentQueue<string>();

    public event Action<string> TaskStarted;
    public event Action<string> TaskCompleted;
    public event Action<string, string> TaskFailed;

    public EventDrivenTaskQueue()
    {
        _workerThread = new Thread(ProcessQueue)
        {
            IsBackground = true
        };
        _workerThread.Start();
    }

    public void RegisterTask(string name, Func<object, CancellationToken, Task<object>> task, TimeSpan timeout)
    {
        _tasks[name] = task;
        _events[name] = new ManualResetEventSlim(false);
        _taskTimeouts[name] = timeout;
    }

    public void EmitEvent(string eventName, object parameter = null)
    {
        if (_events.TryGetValue(eventName, out var eventSlim))
        {
            _taskResults[eventName] = parameter;
            _taskQueue.Enqueue(eventName);
            eventSlim.Set(); // Signal the event
        }
    }

    private void ProcessQueue()
    {
        while (!_cancellationTokenSource.Token.IsCancellationRequested)
        {
            if (_taskQueue.TryDequeue(out var taskName))
            {
                var taskFunc = _tasks[taskName];
                var eventSlim = _events[taskName];
                var timeout = _taskTimeouts[taskName];

                eventSlim.Reset();
                TaskStarted?.Invoke(taskName);

                var cts = new CancellationTokenSource();
                var timeoutTask = Task.Delay(timeout, cts.Token);

                var completedTask = Task.Run(async () =>
                {
                    try
                    {
                        return await taskFunc(_taskResults[taskName], cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        return null;
                    }
                }, cts.Token);

                var finishedTask = Task.WhenAny(completedTask, timeoutTask).Result;

                if (finishedTask == timeoutTask)
                {
                    TaskFailed?.Invoke(taskName, "Timeout");
                    cts.Cancel(); // Cancel the task
                }
                else
                {
                    try
                    {
                        var result = completedTask.Result;
                        TaskCompleted?.Invoke(taskName);
                        if (result != null)
                        {
                            _taskResults[taskName] = result;
                        }
                    }
                    catch (Exception ex)
                    {
                        TaskFailed?.Invoke(taskName, ex.Message);
                    }
                }
            }
            else
            {
                Thread.Sleep(100); // Prevent tight loop if queue is empty
            }
        }
    }

    public void Dispose()
    {
        _cancellationTokenSource.Cancel();
        _workerThread.Join(); // Wait for the worker thread to exit
        foreach (var eventSlim in _events.Values)
        {
            eventSlim.Dispose();
        }
        _cancellationTokenSource.Dispose();
    }
}

使用实例

复制代码
public class Program
{
    public static async Task Main(string[] args)
    {
        using var taskQueue = new EventDrivenTaskQueue();

        taskQueue.TaskStarted += taskId => Console.WriteLine($"Task {taskId} started");
        taskQueue.TaskCompleted += taskId => Console.WriteLine($"Task {taskId} completed");
        taskQueue.TaskFailed += (taskId, reason) => Console.WriteLine($"Task {taskId} failed: {reason}");

        taskQueue.RegisterTask("task1", async (param, cancellationToken) =>
        {
            Console.WriteLine("Task 1 started with param: " + param);
            await Task.Delay(1000, cancellationToken); // Simulate work
            Console.WriteLine("Task 1 completed");
            return "result_from_task1";
        }, TimeSpan.FromSeconds(5));

        taskQueue.RegisterTask("task2", async (param, cancellationToken) =>
        {
            Console.WriteLine("Task 2 started with param: " + param);
            await Task.Delay(1000, cancellationToken); // Simulate work
            Console.WriteLine("Task 2 completed");
            return "result_from_task2";
        }, TimeSpan.FromSeconds(5));

        taskQueue.RegisterTask("done", async (param, cancellationToken) =>
        {
            Console.WriteLine("All tasks done with param: " + param);
            await Task.Delay(500, cancellationToken); // Simulate work
            return null;
        }, TimeSpan.FromSeconds(5));

        // Start the task chain by emitting the first event
        taskQueue.EmitEvent("task1", "initial_param");

        // Emit task2 event when task1 completes
        taskQueue.TaskCompleted += taskId =>
        {
            if (taskId == "task1")
            {
                taskQueue.EmitEvent("task2", taskQueue.TaskResults[taskId]);
            }
            else if (taskId == "task2")
            {
                taskQueue.EmitEvent("done", taskQueue.TaskResults[taskId]);
            }
        };

        // Give time for tasks to complete
        await Task.Delay(10000);
    }
}
相关推荐
threelab几秒前
Three.js 概率统计可视化 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
TG_yunshuguoji1 分钟前
阿里云代理商:阿里云百炼部署的deepseek v4怎么使用?
服务器·人工智能·阿里云·云计算·ai智能体·deepseek v4
kyle~2 分钟前
Linux时间系统1 --- 正确使用时间
java·linux·服务器
星纬智联技术3 分钟前
给 Amp 配置自定义 API:CLIProxyAPI 接入教程
运维·服务器·数据库
m0_372257024 分钟前
RRF和Cross-Encoder rerank怎么实现
开发语言·windows·python
yugi9878386 分钟前
主动噪声控制中的 FXLMS 算法研究与 MATLAB 实现
开发语言·算法·matlab
光影少年7 分钟前
useLayoutEffect 和 useEffect 区别、使用场景
开发语言·前端·javascript
吴声子夜歌11 分钟前
Java——泛型
java·开发语言·泛型
橙色阳光五月天12 分钟前
Qt C++项目的dump文件分析
开发语言·c++·qt
SoveTingღ12 分钟前
【问题解析】Socket已经关闭了,但是端口还处于listening状态?
linux·服务器·c++·qt·socket