[英]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 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.