【问题标题】:Asp.Net core long running/background taskAsp.Net core 长时间运行/后台任务
【发布时间】:2017-12-14 05:56:23
【问题描述】:

以下是在 Asp.Net Core 中实现长时间运行的后台工作的正确模式吗?还是我应该使用某种形式的Task.Run/TaskFactory.StartNewTaskCreationOptions.LongRunning 选项?

    public void Configure(IApplicationLifetime lifetime)
    {
        lifetime.ApplicationStarted.Register(() =>
        {
            // not awaiting the 'promise task' here
            var t = DoWorkAsync(lifetime.ApplicationStopping);

            lifetime.ApplicationStopped.Register(() =>
            {
                try
                {
                    // give extra time to complete before shutting down
                    t.Wait(TimeSpan.FromSeconds(10));
                }
                catch (Exception)
                {
                    // ignore
                }
            });
        });
    }

    async Task DoWorkAsync(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            await // async method
        }
    }

【问题讨论】:

  • 您可以使用像 Hangfire 这样的库来执行此操作。
  • 有关 IApplicationLifetime 的更多详细信息请参阅khalidabuhakmeh.com/…

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


【解决方案1】:

还要检查 .NET Core 2.0 IHostedService。这是documentation。从 .NET Core 2.1 开始,我们将拥有 BackgroundService 抽象类。 可以这样使用:

public class UpdateBackgroundService: BackgroundService
{
    private readonly DbContext _context;

    public UpdateTranslatesBackgroundService(DbContext context)
    {
        this._context= context;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await ...
    }
}

在您的创业公司中,您只需注册课程:

public static IServiceProvider Build(IServiceCollection services)
{
    //.....
    services.AddSingleton<IHostedService, UpdateBackgroundService>();
    services.AddTransient<IHostedService, UpdateBackgroundService>();  //For run at startup and die.
    //.....
}

【讨论】:

  • 面向完整的 .Net 框架时是否也可以使用它?
  • 是的,因为 IHostedService 来自的托管库在 netstandard2.0 包中提供。
  • @Makla 此服务是否在另一个线程上运行?因为我的请求在服务没有完成之前没有完成。
  • @Darem 不,他们不是。执行被阻止,直到您返回 Task。但是如果你使用异步等待,你应该是安全的。 Link 和另一个SO
  • 你能像数据库ID一样将参数传递给ExecuteAsync吗?
【解决方案2】:

以下是在 Asp.Net Core 中实现长时间运行的后台工作的正确模式吗?

是的,这是在 ASP.NET Core 上开始长期运行工作的基本方法。您当然应该使用Task.Run/StartNew/LongRunning - 这种方法总是是错误的。

请注意,您的长时间运行的工作可能随时被关闭,这很正常。如果您需要更可靠的解决方案,那么您应该在 ASP.NET 之外拥有一个单独的后台系统(例如,Azure 函数/AWS lambdas)。还有像 Hangfire 这样的库,可以为您提供一些可靠性,但也有其自身的缺点。

更新:我在how to implement the more reliable approach 上写了一个博客系列,使用具有独立后台系统的持久队列。根据我的经验,大多数开发人员都需要更可靠的方法,因为他们不希望丢失他们长期运行的工作。

【讨论】:

  • 谢谢斯蒂芬-我对这种方法的怀疑正是您提到的“工作可能随时关闭”。假设我不让异步方法出现异常,运行时何时会关闭异步工作?
  • @ubi:ASP.NET 偶尔会回收,只是为了保持清洁。还有常见的原因:操作系统更新、云编排移动、停电等。
  • 再次感谢。你能再解释一下 ASP.NET Core 回收吗?我还没有在其他任何地方读过它(IIS 应用程序池回收除外)。我将其作为控制台应用程序运行。运行时是否重新启动应用程序或请求管道(信号 ApplicationStopping/Stopped 并再次调用 Startup 中的 Configure 方法或类似的东西)?
  • @ubi:啊,既然你是自托管的,它不会回收的。但其他原因仍然存在。
  • @StephenCleary 我很困惑,任何形式的重启都不会简单地再次运行整个应用程序代码吗?在那种情况下,通过Task.Run 启动的后台任务会重新开始吗?或者你的意思是Task.Run 我们不能优雅地 关闭后台任务?但是,在停电(和其他各种情况)的情况下,这似乎也不可能。所以无论如何我们都要做好准备。
猜你喜欢
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 2018-01-12
  • 1970-01-01
相关资源
最近更新 更多