Как изящно фиксировать исключения из событий таймера? - PullRequest
0 голосов
/ 23 мая 2018

В приложении ASP Net Core 2 MVC я использую this BackGroundService (через IHostingService) с приведенной ниже реализацией для обновления объектов с одноэлементным датчиком для панели мониторинга в реальном времени.Тем не менее, я не знаю хорошего способа обеспечить захват любых исключений, возникающих при возникновении события Update.

Примечание. Мне известно о AppDomain.UnhandledException, но я считаю, что это скорееподход кувалдой и хотел бы что-то проще в обслуживании и масштабировании.

Или, есть ли лучший способ периодически обновлять данные в фоновом режиме в ASP.NET Core 2?

public class GaugeUpdater : BackgroundService
{
    private readonly List<IUpdateable> _updatables;

    private Timer _timer;

    public GaugeUpdater (IEnumerable<IUpdateable> updateables)
    {
        _updatables = updateables.ToList();
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (!stoppingToken.IsCancellationRequested)
        {
            await InitializeUpdateables();

            SetTimer();
        }
    }

    private void SetTimer()
    {
        const int intervalMilliseconds = 60_000;

        var interval = new TimeSpan(0, 0, 0, 0, intervalMilliseconds);
        _timer = new Timer(UpdateAll, null, interval, interval);
    }

    private async Task InitializeUpdateables()
    {
        var tasks = _updatables.Select(x => x.Initialize()).ToList();

        await Task.WhenAll(tasks);
    }

    private async void UpdateAll(object state)
    {
        // TODO: Find way to handle exceptions, as awaiting async void makes it impossible for caller to catch.
        // AppDomain.UnhandledException is possible but hard to maintain and handle in this scope.
        _updatables.ForEach(async x => await x.Update());
    }
}

1 Ответ

0 голосов
/ 24 мая 2018

async void может работать для обработчиков событий.Создать и событие и поднять его с помощью таймера.Оттуда вы сможете ожидать асинхронных задач и обрабатывать исключения

public class GaugeUpdater : BackgroundService {
    private readonly List<IUpdateable> _updatables;
    private Timer _timer;

    public GaugeUpdater (IEnumerable<IUpdateable> updateables) {
        _updatables = updateables.ToList();
        Updating += OnUpdating; //Subscribe to event
    }

    private event EventHandler Updating = delegate { };
    private async void OnUpdating(object sender, EventArgs args) {
        try {
            var tasks = _updatables.Select(x => x.Update());
            await Task.WhenAll(tasks);
        } catch {
            //TODO: Logging???
        }
    }

    private void UpdateAll(object state) {
        Updating(this, EventArgs.Empty); //Raise event
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
        if (!stoppingToken.IsCancellationRequested) {
            await InitializeUpdateables();
            SetTimer();
        }
    }

    private void SetTimer() {
        const int intervalMilliseconds = 60_000;
        var interval = new TimeSpan(0, 0, 0, 0, intervalMilliseconds);
        _timer = new Timer(UpdateAll, null, interval, interval);
    }

    private async Task InitializeUpdateables() {
        var tasks = _updatables.Select(x => x.Initialize()).ToList();
        await Task.WhenAll(tasks);
    }
}
...