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