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);
    }
}
相关推荐
rit843249922 分钟前
基于MATLAB的模糊图像复原
开发语言·matlab
fie888927 分钟前
基于MATLAB的声呐图像特征提取与显示
开发语言·人工智能
路由侠内网穿透1 小时前
本地部署开源持续集成和持续部署系统 Woodpecker CI 并实现外部访问
服务器·网络·windows·ci/cd·开源
程序猿小三1 小时前
Linux下基于关键词文件搜索
linux·运维·服务器
_extraordinary_1 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
CsharpDev-奶豆哥1 小时前
ASP.NET中for和foreach使用指南
windows·microsoft·c#·asp.net·.net
@。1242 小时前
对于灰度发布(金丝雀发布)的了解
开发语言·前端
啊?啊?3 小时前
4 解锁 Linux 操作新姿势:man、grep、tar ,创建用户及添加权限等 10 大实用命令详解
linux·服务器·实用指令
_清浅3 小时前
计算机网络【第六章-应用层】
运维·服务器·计算机网络
正在努力的小河3 小时前
Linux 自带的 LED 灯驱动实验
linux·运维·服务器