Создайте отменяемый класс фонового бегуна задачи

Мои требования:

  1. Создайте класс .net 5, который инкапсулирует средство выполнения задачи (т. Е. Оболочку вокруг объекта задачи).
  2. Класс должен сохранять потоки
  3. Потребитель класса должен знать, выполняется ли задача.
  4. Потребитель должен иметь возможность запускать / останавливать и снова запускать бегуна.

Я хотел бы получить любой совет эксперта относительно класса, показанного ниже.

public class TaskWorker : IDisposable
{
    private CancellationTokenSource? _cancellationTokenSource;
    private bool _disposedValue;
    private bool _disposing;
    private readonly Func<CancellationToken, Task> _workerFunction;
    private readonly Action<Exception>? _onErrorCallback;

    public TaskWorker(Func<CancellationToken, Task> workerFunction, Action<Exception>? onErrorCallback = null)
    {
        _workerFunction = workerFunction ?? throw new ArgumentNullException(nameof(workerFunction));
        _onErrorCallback = onErrorCallback;
    }

    public bool IsRunning { get; private set; }
    public bool IsStarted { get; private set; }

    public void Start()
    {
        lock (this)
        {
            if (_cancellationTokenSource != null)
                throw new InvalidOperationException();
            
            if (IsRunning)
                throw new InvalidOperationException();

            _cancellationTokenSource = new CancellationTokenSource();
            Task.Run(() => WorkerFuncCore(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
            IsStarted = true;
        }
    }

    public void Stop()
    {
        lock (this)
        {
            if (_cancellationTokenSource == null)
                return;

            _cancellationTokenSource.Cancel();
            _cancellationTokenSource.Dispose();
            _cancellationTokenSource = null;
            IsStarted = false;
        }
    }

    private async void WorkerFuncCore(CancellationToken cancellationToken)
    {
        try
        {
            IsRunning = true;
            await _workerFunction(cancellationToken);
        }
        catch (OperationCanceledException)
        {
            //do nothing
        }
        catch (Exception ex)
        {
            if (!_disposing && !_disposedValue)
            {
                _onErrorCallback?.Invoke(ex);
            }
        }

        IsRunning = false;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                _disposing = true;
                try
                {
                    _cancellationTokenSource?.Cancel();
                    _cancellationTokenSource = null;
                }
                finally
                {
                    _disposing = false;
                }
            }

            _disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
}

Пока мои опасения:

  1. Я должен заблокировать this под Dispose(bool disposing) непосредственно перед отменой токена?

  2. Я правильно говорю, что НЕТ способа прервать выполнение функции, переданной рабочему? другими словами, если пользовательский код не соблюдает / не проверяет переданный токен отмены, как я могу прервать его после вызова Stop() функция? Например, если я использую такую ​​функцию:

     private async Task BackgroundTaskRunner(CancellationToken cancellationToken)
     {
         //THIS STOPS FOREVER AND THE WORKER CAN'T DO MUCH !!!
         await Task.Delay(Timeout.Infinite); //<-- simulate consumer code error not passing the cancellation token
     }
    

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *