web-dev-qa-db-ja.com

ASP.Netコアミドルウェアを使用してバックグラウンドタスクを開始する

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が完了するまでページの読み込みに遅延が発生することです。 DoAsyncを実行した直後にnext.Invoke()が呼び出されるように、上記を正しく実装するにはどうすればよいですか?

6
James B

ASP.NETは、バックグラウンドタスク用に設計されていません。私は強く信頼できるキュー(Azureキュー/ MSMQ)を使用して、Azure Functions/WebJobs/Worker Roles/Win32サービスなどの適切なアーキテクチャを使用することをお勧めします/など)ASP.NETアプリがそのサービスと通信するため。

ただし、本当にしたい場合、およびリスクを受け入れる意思がある場合(具体的には、作業が中止される可能性がある場合)、-を使用できます。 IApplicationLifetime

4
Stephen Cleary

ASP.NET Core 2では、IHostedServiceはバックグラウンドタスクを実行するように設計されています。 IHostedServiceをシングルトンとして登録すると、起動時に自動的に開始されます。

implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x

asp-net-core-background-processing

16
Peter

Asp.Netコア2.1はバックグラウンドタスクを使用するため、 IHostedService 基本クラスから派生してBackgroundServiceを実装すると非常に便利です。これが ここ から取られたサンプルです:

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でホストされている場合)、アプリプールのリサイクルのためにシャットダウンされる可能性があります)。一部のシナリオでは、非常にうまく適用できます。

6
AlbertK

の代わりに

_await serviceWithAsyncTask .DoAsync();
_

あなたが使うことができます

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

このアプローチでは、スレッドプールから追加のスレッドが使用されます。これはもちろん、コードをメインスレッド以外のスレッドで実行する場合の要件です:-)

このブロックの後に配置されたコードはすべてすぐに実行されます。また、Webサーバープロセス(ケストラル)がIISまたは使用しているリバースプロキシによってリサイクルされる場合、バックグラウンドワーカーはすぐに中止されるため、バックグラウンドワーカーは防御的に作成する必要があります。これを念頭に置いてください。

また、SomeMethod()自体はasyncメソッドではないことに注意してください。ただし、バックグラウンドスレッドから呼び出されているため、非同期で実行されています(つまり、メインスレッドから独立しています)。

3
Ron C

バックグラウンド処理を管理するためのHangFireを見てください。NetCoreでうまく機能します: https://www.hangfire.io/

1
Mark Redman