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);
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于实现Metric(度量标准)的问题,Java提供了多种方式,具体取决于你要实现哪种Metric。以下是两种常见的Java实现Metric的方式: 1. 实现接口 Java中有很多接口可以用来实现Metric,比如Comparable、Comparator、Metric等等。如果你要实现自定义的Metric,可以考虑实现Metric接口。Metric接口定义了一个方法,用于计算两个对象之间的距离或相似度。你可以实现该接口,并重写其中的方法,以实现自定义的Metric。例如: ``` public interface Metric<T> { double distance(T a, T b); } ``` 在该接口中,我们定义了一个distance方法,用于计算两个对象之间的距离。你可以在实现该接口的类中重写该方法,以实现自定义的Metric。 2. 使用第三方库 Java中有很多第三方库可以用来实现Metric,比如Apache Commons Math、Jama、ELKI等等。这些库提供了多种常用的Metric实现,比如欧几里得距离、曼哈顿距离、余弦相似度等等。你可以选择一个适合你的库,并使用其提供的Metric实现。例如,使用Apache Commons Math库计算欧几里得距离: ``` import org.apache.commons.math3.ml.distance.EuclideanDistance; public class Main { public static void main(String[] args) { EuclideanDistance metric = new EuclideanDistance(); double[] a = {1, 2, 3}; double[] b = {4, 5, 6}; double distance = metric.compute(a, b); System.out.println(distance); } } ``` 在该例子中,我们使用了Apache Commons Math库中提供的EuclideanDistance实现,计算了两个向量之间的欧几里得距离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值