【问题标题】:Start Background Task using ASP.Net Core Middleware使用 ASP.Net Core 中间件启动后台任务
【发布时间】:2017-06-05 11:08:43
【问题描述】:

我正在尝试在 ASP.Net Core 中加载页面时运行异步任务,即,我希望任务在用户路由到页面后立即运行,但在任务完成之前显示页面完全的。似乎使用 ASP.Net 核心,您可以使用中间件来执行此类任务。所以我尝试将以下内容添加到Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
        {

// Other configurations here
app.Use(async (context, next) =>
            {
                if (context.Request.Path.Value.Contains("PageWithAsyncTask"))
                {
                    var serviceWithAsyncTask = serviceProvider.GetService<IMyService>();
                    await serviceWithAsyncTask .DoAsync();
                }
                await next.Invoke();
            });

app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

}

上面的问题是在DoAsync 完成之前页面加载存在延迟,因为在DoAsync 完成之前我们不会调用next.Invoke()。如何正确实现上述操作,以便在 DoAsync 运行后立即调用 next.Invoke()

【问题讨论】:

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


    【解决方案1】:

    在 ASP.NET Core 2 中,IHostedService 旨在运行您的后台任务。 将 IHostedService 注册为 Singleton 并在启动时自动启动:

    implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x

    asp-net-core-background-processing

    【讨论】:

      【解决方案2】:

      由于Asp.Net core 2.1 使用后台任务,通过派生BackgroundService 基类来实现IHostedService 非常方便。这是取自here的样本:

      public class MyServiceA : BackgroundService
      {
          protected override async Task ExecuteAsync(CancellationToken stoppingToken)
          {
              Console.WriteLine("MyServiceA is starting.");
      
              stoppingToken.Register(() => Console.WriteLine("MyServiceA is stopping."));
      
              while (!stoppingToken.IsCancellationRequested)
              {
                  Console.WriteLine("MyServiceA is doing background work.");
      
                  await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
              }
      
              Console.WriteLine("MyServiceA background task is stopping.");
          }
      }
      

      那就在Startup.ConfigureServices注册吧:

      services.AddSingleton<IHostedService, MyServiceA>();
      

      正如 Stephen Cleary 所指出的,Asp.Net 应用程序可能不是后台任务的最佳位置(例如,当应用程序托管在 IIS 中时,它可能会因为应用程序池回收而关闭),但在某些情况下,它可以非常适用好吧。

      【讨论】:

        【解决方案3】:

        ASP.NET 不是为后台任务而设计的。我强烈建议使用适当的体系结构,例如 Azure Functions / WebJobs / Worker Roles / Win32 services / 等,并为 ASP.NET 应用程序提供可靠的队列(Azure queues / MSMQ / etc)为其服务。

        但是,如果您真的想要 - 并且愿意接受风险(特别是,您的工作可能会中止),那么您可以使用 IApplicationLifetime

        【讨论】:

        • 使用 Quartz.Net 来调度作业的 Asp.Net Web API 应用程序是否超出了这个范围?
        • @ibubi:Quartz.Net 和 HangFire 各有各的缺点;我认为它们是IApplicationLifetime 的替代品。
        • 谢谢,但我不明白,周围有数百个 Asp.net&Quartz.Net 或 Hangfire 实现教程,请您参考一个简短的文档来解释为什么我们应该避免使用这两个或我们的Asp.Net 中的自定义库?
        • @ibubi 我从未使用过 Quartz.NET。但至少使用 Hangfire,您需要确保自己的 Web 应用程序保持持续运行。现在它占用了您的网站可能使用的资源,现在您无法将其与您的网站分开扩展。当然,假设您在 Web 应用程序项目中托管 Hangfire。我已经成功地将 Hangfire 作为一个单独的控制台应用程序托管,我使用 TopShelf 作为 Windows 服务运行 - 这消除了缺点,但意味着您需要一个单独的项目来部署。
        • @ibubi:我建议您问自己的问题。在回答 cmets 中有很多要讨论的内容。
        【解决方案4】:

        代替

        await serviceWithAsyncTask .DoAsync();
        

        你可以使用

         ThreadPool.QueueUserWorkItem(delegate {
               SomeMethod();
           });
        

        在这种方法中,将从线程池中使用一个额外的线程,如果您希望代码在主线程以外的线程上运行,这当然是一个要求:-)

        放置在此块之后的任何代码都将立即运行。另请注意,如果您的 Web 服务器进程 (kestral) 被 IIS 或您使用的任何反向代理回收,那么您的后台工作人员将立即中止。因此,您的后台工作人员需要在编写时考虑到这一点。

        另外请注意SomeMethod() 本身并不是async 方法。但它是从后台线程调用的,因此它是异步运行的(即独立于主线程。)

        【讨论】:

          【解决方案5】:

          看看 HangFire 用于管理后台处理,在 .Net Core 中运行良好:https://www.hangfire.io/

          【讨论】:

            猜你喜欢
            • 2017-12-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-02
            • 1970-01-01
            相关资源
            最近更新 更多