【问题标题】:ASP.NET Core event based background tasks with hosted services具有托管服务的基于 ASP.NET Core 事件的后台任务
【发布时间】:2018-12-02 12:30:25
【问题描述】:

我在使用 ASP.NET Core 托管服务中的后台任务的 while 循环和事件方面遇到了一些问题。我试图让我的 Progress_Changed 事件从while (!cancellationToken.IsCancellationRequested) 部分中触发,以便在应用程序运行时连续捕获数据。我一直在关注这些指南:

Background tasks with hosted services in ASP.NET Core

Implement background tasks in microservices with IHostedService and the BackgroundService class

如何在保持 BackgroundService 连续循环的同时捕获事件,以便始终能够获取数据?我希望将它与 SignalR 一起使用,以便将数据馈送到集线器。

public class MyBackgroundService : BackgroundService
{
    private readonly ICustomService _service;
    private IProgress<JSONMessage> _progress;

    public MyBackgroundService(ICustomService service)
    {
        _service = service;
        _progress = new Progress<JSONMessage>();
        _progress.ProgressChagned += Progress_Changed;
    {

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        await _service.StartService(_progress);

        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
        }
    }

    private void Progress_Changed(object s, JSONMessage e)
    {
        Console.WriteLine(e.Id);
    }
}

【问题讨论】:

  • 运行此代码时当前发生了什么?换句话说,它有什么问题?异常、行为等...
  • 事件在早期触发,或者至少在我单步执行代码时触发,但在直接运行时它永远不会输出。

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


【解决方案1】:

由于各种原因,在 IIS 中长时间运行任务可能会很棘手。将这种东西委托给一个工作类似于 Hangfire 的库可能更容易。 https://www.hangfire.io/.

【讨论】:

    【解决方案2】:

    我可能是错的,但这对我来说似乎是一个可能的僵局。默认情况下,await 捕获当前的SynchronizationContext,然后在完成后回发给它。这在 IIS/ASP.NET 中变得相当冒险,原因有很多,我不会深入探讨。试试这个代码:

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        await _service.StartService(_progress).ConfigureAwait(false);
    
        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
        }
    }
    

    这里所做的唯一更改是禁用回发到我所说的捕获的上下文。请注意,这意味着您在调用await 后可能处于不同的线程中。因此,您可以认为这是一种 hack,但我在该方法中看不到任何需要回发的内容。

    如果这不能解决问题,我会在 release 构建中附加一个调试器。或者使用分析器来查看到底发生了什么。

    【讨论】:

      猜你喜欢
      • 2021-02-06
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      相关资源
      最近更新 更多