繁体   English   中英

使用 ASP.Net Core Middleware 启动后台任务

[英]Start Background Task using ASP.Net Core Middleware

我试图在 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() 如何正确实现上述内容, next.Invoke()在运行DoAsync后立即调用next.Invoke()

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

在微服务中实现后台任务与 ihostedservice-and-the-backgroundservice-class-net-core-2-x

asp-net-core-background-processing

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

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 中时,它可能会因为应用程序池回收而被关闭),但对于某些场景,它可以很好地应用。

ASP.NET 不是为后台任务设计的。 强烈建议使用适当的架构,例如 Azure Functions / WebJobs / Worker Roles / Win32 services / etc,以及一个可靠的队列(Azure queues / MSMQ / etc),以便 ASP.NET 应用程序与其服务对话。

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

而不是

await serviceWithAsyncTask .DoAsync();

你可以用

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

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

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

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

查看用于管理后台处理的 HangFire,在 .Net Core 中效果很好: https ://www.hangfire.io/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM