我在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
完成之前,页面加载会有延迟,因为在next.Invoke()
完成之前我们不会调用DoAsync
。如何正确实施上述内容,以便在next.Invoke()
运行后立即调用DoAsync
?
答案 0 :(得分:15)
在ASP.NET Core 2中,IHostedService旨在运行您的后台任务。 将IHostedService注册为Singleton,并在启动时自动启动:
答案 1 :(得分:5)
自 Asp.Net核心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中时,由于应用程序池回收,可以将其关闭),但是在某些情况下,可以应用得很好。
答案 2 :(得分:4)
ASP.NET不是为后台任务设计的。我强烈建议使用适当的体系结构,例如Azure Functions / WebJobs / Worker Roles / Win32 services / etc,以及可靠的队列(Azure队列/ MSMQ /等),以便ASP.NET应用程序进行通话它的服务。
但是,如果确实想要 - 并且愿意接受风险(具体而言,您的工作可能会中止),那么您可以使用IApplicationLifetime
。
答案 3 :(得分:3)
而不是
await serviceWithAsyncTask .DoAsync();
你可以使用
ThreadPool.QueueUserWorkItem(delegate {
SomeMethod();
});
在这种方法中,将从线程池中使用另一个线程,如果您希望代码在主线程以外的线程上运行,这当然是一个要求:-)
此块后面的任何代码都会立即运行。另请注意,如果您的Web服务器进程(kestral)由IIS或您正在使用的任何反向代理回收,那么您的后台工作程序将立即中止。因此,考虑到这一点,你的背景工作者需要以防御性方式编写。
另请注意,SomeMethod()
本身不是async
方法。但它是从后台线程调用的,所以它是异步运行的(即独立于主线程。)
答案 4 :(得分:1)
查看HangFire以管理后台处理,在.Net Core中运行良好:https://www.hangfire.io/