2017-06-05 45 views
1

我试图在ASP.Net Core中加载一个页面时运行一个异步任务,也就是说,我希望任务尽快在用户路由到页面时运行,但对于该任务完成之前要显示的页面。看来,使用ASP.Net核心,您可以使用中间件来执行此类任务。所以我试图下面添加到Startup.cs使用ASP.Net核心中间件启动后台任务

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运行后立即调用的?

回答

3

ASP.NET并不是为后台任务设计的。 I strong建议使用Azure Functions/WebJobs/Worker Roles/Win32 services/etc等适当的体系结构,为ASP.NET应用程序提供可靠的队列(Azure队列/ MSMQ/etc)以与其服务交谈。

但是,如果你真的想要 - 并愿意接受风险(特别是,你的工作可能会中止),那么你可以使用IApplicationLifetime

+0

* Asp.Net的Web API应用程序,它使用Quartz.Net计划作业*出这个范围分辩的? – ibubi

+0

@ibubi:Quartz.Net和HangFire各有其缺点;我认为它们是'IApplicationLifetime'的替代品。 –

+0

谢谢,但我不明白,数以百计的Asp.net和Quartz.Net或Hangfire实现教程都提供了建议,请您参考一个简要文档解释为什么我们应该避免在Asp.Net中使用这两个或我们的自定义库? – ibubi

1

而不是

await serviceWithAsyncTask .DoAsync(); 

你可以使用

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

在这种方法中附加线程池将在线程池中使用,如果您希望代码在除主线程之外的其他线程上运行,则该线程当然是必需的:-)

放在此块之后的任何代码都将立即运行。另外请注意,如果您的Web服务器进程(kestral)被IIS回收或您正在使用的任何反向代理,那么您的后台工作人员将立即中止。所以你的背景工作者需要谨记防御性的书写。

另请注意,SomeMethod()本身并不是async的方法。但它是从后台线程调用的,因此它运行异步(即独立于主线程)。