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