Asp.Net MVC 5-长期运行的任务-如何确保在IIS回收AppPool时不会抛弃工作线程?

Ren*_*Ren 1 .net c# asp.net-mvc task-parallel-library async-await

我有一个数据处理MVC应用程序,该应用程序可以处理从100MB到2GB的上载文件大小,并且包含一些长时间运行的操作。用户将上载文件,并将处理这些文件中的数据,然后最后将对数据的某些分析发送给相关的用户/客户端。

处理数据至少要花费几个小时,因此为了确保用户不必一直等待,我分派了一个单独的任务来执行此长时间运行的操作。这样,一旦文件被服务器接收并存储在磁盘上,用户将获得带有ReferenceID的响应,并且他们可以关闭浏览器。

到目前为止,它一直按预期运行,但是在阅读了有关在MVC中使用即弃模式以及在回收期间IIS抛弃工作线程的问题之后,我对此方法有所关注。

这种方法仍然安全吗?如果不是,如何确保正在处理数据的线程在完成处理并将数据发送给客户端之前不会消失?(以相对简单的方式)

该应用程序在.NET 4.5上运行,所以不要以为我可以使用 HostingEnvironment.QueueBackgroundWorkItem。

在控制器上使用Async / Await是否有帮助?

我还考虑过在文件存储到磁盘后,在应用服务器上使用消息队列来存储消息,然后将DataProcessor设置为单独的服务/进程,然后侦听队列。如果队列是可恢复的,那么它将向我保证,即使服务器崩溃或线程在完成处理数据之前被丢弃后,消息最终仍将最终得到处理。这是更好的方法吗?

我当前的设置如下

控制者

public ActionResult ProcessFiles() 
{    
    HttpFileCollectionBase uploadedfiles = Request.Files;    

    var isValid = ValidateService.ValidateFiles(uploadedFiles);

    if(!isValid){
        return View("Error");
    }

    var referenceId = DataProcessor.ProcessData(uploadedFiles);

    return View(referenceId);    
}
Run Code Online (Sandbox Code Playgroud)

商业逻辑

public Class DataProcessor 
   {    
     public int ProcessFiles(HttpFileCollectionBase uploadedFiles) 
     {    
      var referenceId = GetUniqueReferenceIdForCurrentSession();

      var location = SaveIncomingFilesToDisk(referenceId, uploadedFiles);

      //ProcessData makes a DB call and takes a few hours to complete. 

      TaskFactory.StartNew(() => ProcessData(ReferenceId,location))
                 .ContinueWith((prevTask) => 
      {
         Log.Info("Completed Processing. Carrying on with other work");

         //Below method takes about 30 mins to an hour
         SendDataToRelatedClients(ReferenceId);  
      }    
      return referenceId;
     }

   }
Run Code Online (Sandbox Code Playgroud)

参考文献

http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html

Apppool回收和Asp.net与线程?

Ste*_*ary 5

这种方法仍然安全吗?

从来都不安全。

在控制器上使用Async / Await是否有帮助?

没有。

该应用程序在.NET 4.5上运行,因此不要认为我现在可以使用HostingEnvironment.QueueBackgroundWorkItem。

我有一个AspNetBackgroundTasks库,该库实际上与QueueBackgroundWorkItem(略有不同)执行相同的操作。然而...

我还考虑过在文件存储到磁盘后,在应用服务器上使用消息队列来存储消息,然后将DataProcessor设置为单独的服务/进程,然后侦听队列。如果队列是可恢复的,那么它将向我保证,即使服务器崩溃或线程在完成处理数据之前被丢弃后,消息最终仍将最终得到处理。这是更好的方法吗?

是。这是唯一可靠的方法。这就是我在博客文章中所说的“适当的分布式体系结构” 。