C# Asp.NETMVC5-长时间运行任务-如何确保工作线程获胜';IIS回收应用程序池时不会被丢弃?

C# Asp.NETMVC5-长时间运行任务-如何确保工作线程获胜';IIS回收应用程序池时不会被丢弃?,c#,.net,asp.net-mvc,async-await,task-parallel-library,C#,.net,Asp.net Mvc,Async Await,Task Parallel Library,我有一个数据处理MVC应用程序,它可以处理从100MB到2GB的上传文件,并包含一些长时间运行的操作。用户将上传文件,并对这些文件中的数据进行处理,最后将数据的一些分析发送给相关用户/客户 处理数据至少需要几个小时,因此为了确保用户不必一路等待,我已经启动了一个单独的任务来完成这个长时间运行的操作。这样,一旦服务器接收到文件并将其存储在磁盘上,用户将收到带有ReferenceID的响应,并可以关闭浏览器 到目前为止,它一直工作得很好,但在阅读了MVC中使用Fire and Forget模式的问题

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

处理数据至少需要几个小时,因此为了确保用户不必一路等待,我已经启动了一个单独的任务来完成这个长时间运行的操作。这样,一旦服务器接收到文件并将其存储在磁盘上,用户将收到带有ReferenceID的响应,并可以关闭浏览器

到目前为止,它一直工作得很好,但在阅读了MVC中使用Fire and Forget模式的问题以及工作线程在回收过程中被IIS丢弃的问题后,我对这种方法感到担忧

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

该应用程序在.NET 4.5上运行,因此目前我无法使用
HostingEnvironment.QueueBackgroundWorkItem

在控制器上使用异步/等待是否有帮助

我还考虑过,一旦文件存储到磁盘上,就使用AppServer上的消息队列来存储消息,然后将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);    
}
业务逻辑

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;
     }

   }
参考资料

这种方法仍然安全吗

这从来都不安全

在控制器上使用异步/等待是否有帮助

没有

该应用程序在.NET 4.5上运行,因此目前我无法使用HostingEnvironment.QueueBackgroundWorkItem

我有一个基本上与
QueueBackgroundWorkItem
做相同的事情(有一些细微的区别)。然而

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

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

这种方法仍然安全吗

这从来都不安全

在控制器上使用异步/等待是否有帮助

没有

该应用程序在.NET 4.5上运行,因此目前我无法使用HostingEnvironment.QueueBackgroundWorkItem

我有一个基本上与
QueueBackgroundWorkItem
做相同的事情(有一些细微的区别)。然而

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


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

不,它不安全。在服务器上创建一个服务应用程序,用于处理这些请求并发布结果。如果您托管在Azure上,请利用他们的服务。

不,这不安全。在服务器上创建一个服务应用程序,用于处理这些请求并发布结果。如果您托管在Azure上,请利用他们的服务。

我不建议在ASP.NET中启动非ASP.NET控制的线程。相反,进程外(即单独的进程)可执行文件更有意义。您可以使用计划任务监视数据库中的新“未处理数据”,然后根据需要在后台完全远离应用程序池进行处理。同意@rudiviser。。。使用web应用程序来运行这种进程对我来说似乎有点过分了。您应该允许通过web服务器进行上传,并在负责数据处理的单独任务上运行作业、计划任务和windows服务。您的web服务器只需要侦听进度。。。但这可以通过在数据存储中的某处添加一个
进度行来实现。这样,您就可以确保不会在webapp上出现应用程序池或线程阻塞。谢谢您的建议。我的计划是为最佳解决方案做同样的事情。然而,由于它是一个现有的应用程序,它首先需要解决许多依赖关系,然后让组件(最好是windows服务)独立工作。我很快就会对此做出决定。我选择了Hangfire,这是Stephen在他的博客文章中提到的一个类似的应用程序。它不是最优的,但很有效。我不建议在ASP.NET中启动非ASP.NET控制的线程,真的。相反,进程外(即单独的进程)可执行文件更有意义。您可以使用计划任务监视数据库中的新“未处理数据”,然后根据需要在后台完全远离应用程序池进行处理。同意@rudiviser。。。使用web应用程序来运行这种进程对我来说似乎有点过分了。你