Обработчик повторяющегося действия

В моем приложении у меня есть класс, отвечающий за сохранение в файле текущего статуса приложения (модели) при его изменении:

public class BackupAgent
{
    private readonly Model _model;

    public BackupAgent(Model model)
    {
        _model = model;
        _model.Changed += Save;
    }

    private void Save()
    {
        // serialize model and save it to a file
        ...
    }
}

Он работает нормально, но при большом количестве модификаций файл записывается снова и снова.

Я вышел с RecurringActionHandler которые гарантируют, что

  • в Save метод не вызывается дважды за минимальное время.
  • в Save метод всегда вызывается (рано или поздно) после модификации.

Он используется так:

public class BackupAgent
{
    private readonly Model _model;
    private readonly RecurringActionHandler _saveHandler;

    public BackupAgent(Model model)
    {
        _model = model;
        _saveHandler = new RecurringActionHandler(Save, TimeSpan.FromMilliseconds(100));

        _model.Changed += RequestSave;
    }

    private void RequestSave() => _saveHandler.RequestCall();

    private void Save()
    {
        // serialize model and save it to a file
        ...
    }
}

Вот моя текущая реализация:

public class RecurringActionHandler
{
    // Action to call recurrently 
    private readonly Action _action;

    // a lock to protect _hasTask and _isCallRequested
    private readonly object _lock = new();

    // minimum time span between two calls to _action
    private readonly TimeSpan _minimumRestTime;

    // a boolean indicating whether a task is already running or not
    private bool _hasTask;

    // a boolean indicating whether a call to _action is request or not
    private bool _isCallRequested;

    public RecurringActionHandler(Action action, TimeSpan minimumRestTime)
    {
        _action = action;
        _minimumRestTime = minimumRestTime;
    }

    public void RequestCall()
    {
        lock (_lock)
        {
            _isCallRequested = true;

            if (_hasTask)
                return;

            _hasTask = true;
            Task.Run(Work);
        }
    }

    private async Task Work()
    {
        for (;;)
        {
            lock (_lock)
            {
                if (!_isCallRequested)
                {
                    _hasTask = false;
                    break;
                }

                _isCallRequested = false;
            }

            _action();
            await Task.Delay(_minimumRestTime).ConfigureAwait(false);
        }
    }
}

Я ищу совета по коду и именам методов / классов. Является Throttling подходящее имя здесь?

0

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

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