【问题标题】:How to gracefully capture exceptions from timer events?如何优雅地从定时器事件中捕获异常?
【发布时间】:2018-05-23 03:02:18
【问题描述】:

在 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());
    }
}

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc asp.net-core-2.0


    【解决方案1】:

    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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-02-23
      • 1970-01-01
      • 2012-11-12
      • 1970-01-01
      • 2018-02-26
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 2015-12-14
      相关资源
      最近更新 更多