using Serilog; using ApplicationException = System.ApplicationException; using TaskExtensions = MesETL.Shared.Helper.TaskExtensions; namespace MesETL.App.Services; /// /// 快速批量创建和等待任务 /// public class TaskManager { private int _runningTaskCount; public int RunningTaskCount => _runningTaskCount; public int MaxTaskCount { get; } public event Action? OnException; public event Action? OnTaskCompleteSuccessfully; public TaskManager(int maxTaskCount) { MaxTaskCount = maxTaskCount; } public async ValueTask CreateTaskAsync(Func func, CancellationToken cancellationToken = default) { await TaskExtensions.WaitUntil(() => _runningTaskCount < MaxTaskCount, 25, cancellationToken); return RunTask(func, cancellationToken); } public async ValueTask CreateTaskAsync(Func func, object? arg, CancellationToken ct = default) { await TaskExtensions.WaitUntil(() => _runningTaskCount < MaxTaskCount, 25, ct); return RunTaskNoClosure(func, arg, ct); } private Task RunTask(Func func, CancellationToken cancellationToken = default) { var task = Task.Run(async () => { // Log.Logger.Verbose("[任务管理器] 新的任务已创建"); Interlocked.Increment(ref _runningTaskCount); try { await func(); OnTaskCompleteSuccessfully?.Invoke(); } catch(Exception ex) { OnException?.Invoke(ex); Log.Logger.Error(ex, "[任务管理器] 执行任务时出错"); } finally { Interlocked.Decrement(ref _runningTaskCount); } }, cancellationToken); return task; } private Task RunTaskNoClosure(Func func, object? arg, CancellationToken cancellationToken = default) { var task = Task.Factory.StartNew(async obj => // 性能考虑,这个lambda中不要捕获任何外部变量! { // Log.Logger.Verbose("[任务管理器] 新的任务已创建"); if (obj is not Tuple, object?> tuple) throw new ApplicationException("这个异常不该出现"); Interlocked.Increment(ref _runningTaskCount); try { await tuple.Item1(tuple.Item2); OnTaskCompleteSuccessfully?.Invoke(); } catch(Exception ex) { OnException?.Invoke(ex); Log.Logger.Error(ex, "[任务管理器] 执行任务时出错"); } finally { Interlocked.Decrement(ref _runningTaskCount); } }, Tuple.Create(func, arg), cancellationToken).Unwrap(); return task; } }