使用ASP.Net核心中间件

时间:2017-06-05 11:08:44

标签: c# asp.net 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完成之前,页面加载会有延迟,因为在next.Invoke()完成之前我们不会调用DoAsync。如何正确实施上述内容,以便在next.Invoke()运行后立即调用DoAsync

5 个答案:

答案 0 :(得分:15)

在ASP.NET Core 2中,IHostedService旨在运行您的后台任务。 将IHostedService注册为Singleton,并在启动时自动启动:

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

asp-net-core-background-processing

答案 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/