【问题标题】:ASP.NET HTTPHandlers and long running processesASP.NET HTTPHandlers 和长时间运行的进程
【发布时间】:2010-10-11 15:40:43
【问题描述】:

这是一个多部分的问题。

我有一个可能需要几分钟才能完成的过程,它是通过使用异步 javascript 请求调用 HTTPHandler 来运行的。

问题 1:如何确保此请求在服务器和客户端都不会超时?

问题 2:是否可以在处理过程中从 HTTPHandler 发出数据,这些数据在最终页面完成之前发送回 XmlHttpRequest 对象?

我想计算实际工作量和完成的回报百分比。我猜这是可能的。

有什么建议吗?

编辑:

快速测试:

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        for (int i = 0; i < 100; i++)
        {
            context.Response.Write("Hello World " + i + Environment.NewLine);
            System.Threading.Thread.Sleep(500);
            context.Response.Flush();
        }            
    }

将 Hello World 一点一点地推送到客户端...这适用于同步请求,我将查看 xmlHttpRequest 是否为每一行获取 readystatechange 事件。

我一直避免在 ASP.NET 应用程序上使用多线程,因为您无法控制工作进程何时终止,这将导致其生成的所有线程都终止。

相反,既然 IIS 已经为您这样做了,为什么还要重新发明一个单独的线程池。

【问题讨论】:

标签: asp.net ajax xmlhttprequest httphandler


【解决方案1】:

我过去所做的是在一个新线程上启动长时间运行的进程,并在进程类上有一个属性来说明完成百分比。然后每隔一段时间,浏览器就可以对 HttpHandler 进行 AJAX 调用,该 HttpHandler 只是轮询该 % complete 属性。这样 HttpHandler 会立即返回。

如果作业很重要,可能需要考虑一些问题,例如缓解工作进程在作业中回收或保存作业状态以便重新启动。如果job非常关键,最好写一个windows service来执行job,使用Remoting之类的查询进度。

【讨论】:

    【解决方案2】:
    1. 您可以在 web.config 中更改请求超时值,例如: &lt;configuration&gt; &lt;system.web&gt;&lt;httpRuntime executionTimeout="1000" /&gt;&lt;/system.web&gt;&lt;/configuration&gt;

    2. 据我所知,没有办法将信息发送回同一个异步请求。我见过的大多数 Ajax UI 都是通过拥有一个静态类来创建该行为的,该类保存正在运行的任务的统计信息,然后使用另一个异步请求或 iframe 轮询它。 Neat Upload Control 就是一个很好的类似例子。

    【讨论】:

      【解决方案3】:

      这里有一个想法......

      如果您有一个需要“几分钟”来处理的进程,您最好创建一个单独的线程(或单独的线程队列),而不是使用 ASP.NET 工作线程。这是因为如果您用完所有工作线程,那么您的 Web 服务器可能会挂起。有关此问题的更多信息:http://msdn.microsoft.com/en-us/magazine/cc164128.aspx

      您的第一个 AJAX 请求是启动该进程。随后的调用将获取进程的状态,包括完成百分比。使用计时器轮询(每隔几秒或任何似乎效果最好的方式)以获取完成百分比,直到全部完成。

      AJAX 请求 (XmlHttpRequest) 在客户端本身没有超时 (http://luke.breuer.com/tutorial/xmlhttprequest.aspx... 向下滚动到超时),但我认为让它们关闭几分钟并不是一个好主意尽可能工作:

      【讨论】:

        【解决方案4】:

        根据定义,HTTP 请求是无状态的。正如其他人指出的那样 - 您无法预测 IIS 何时会回收进程。

        更好的方法是创建一个 Windows 服务来完成真正的工作,并创建一个 HTTPHandler 或页面或其他任何东西来查询它的进度并将其返回给客户端。您可以将服务安装在同一台机器上,然后使用管道或任何您想在页面/处理程序与服务之间连接的远程处理通道。

        【讨论】:

          【解决方案5】:

          为了它的价值,

          public void ProcessRequest(HttpContext context)
          {
              context.Response.ContentType = "text/plain";
              for (int i = 0; i < 100; i++)
              {
                  context.Response.Write("Hello World " + i + Environment.NewLine);
                  System.Threading.Thread.Sleep(500);
                  context.Response.Flush();
              }            
          }
          

          在客户端:

          httpObject.onreadystatechange = function()
          {
              // This is called whenever Flush() is called on the server.
              // when readyState = 4, everything is done, but I can check responseText at anytime.
          }
          

          工作得很好。

          【讨论】:

          • 应用池回收不会影响这个吗?
          【解决方案6】:

          从本网站下载源文件

          http://www.stonebroom.com/dafiles/6744-code.zip

          检查网址 ~/loadpost/stagedloading.aspx。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-08
            相关资源
            最近更新 更多