In an ASP.net core application I spawn background tasks in one request, which can finish by themselves, or be cancelled by a second request. I have the following implementation, but I feel there should be a better way of achieving what I want? Does somebody have some experience with this problem?
public sealed class SomeService
{
private record BackgroundTask(Task Task,
CancellationTokenSource CancellationTokenSource);
private readonly ConcurrentDictionary<Guid, BackgroundTask> _backgroundTasks
= new();
public void Start(Guid id)
{
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
var task = Task.Run(async () =>
{
try
{
await Task.Delay(1000, cancellationToken);
}
finally
{
_backgroundTasks.TryRemove(id, out _);
}
}, cancellationToken);
_backgroundTasks.TryAdd(id, new BackgroundTask(task, cancellationTokenSource));
}
public void Cancel(Guid id)
{
_backgroundTasks.TryGetValue(id, out var backgroundTask);
if (backgroundTask == null)
{
return;
}
backgroundTask.CancellationTokenSource.Cancel();
try
{
backgroundTask.Task.GetAwaiter().GetResult();
}
catch (OperationCanceledException e)
{
// todo: cancellation successful...
}
}
}