MES-ETL/MesETL.App/Services/TaskManager.cs

86 lines
2.9 KiB
C#
Raw Normal View History

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
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 () =>
{
// 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);
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中不要捕获任何外部变量!
{
// Log.Logger.Verbose("[任务管理器] 新的任务已创建");
2024-01-29 09:29:16 +08:00
if (obj is not Tuple<Func<object?, Task>, object?> tuple)
throw new ApplicationException("这个异常不该出现");
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);
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
}
}