簡體   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