2009-03-05 30 views
2

这是一个多部分问题。ASP.NET HTTPHandlers和长时间运行的进程

我有一个过程,可能需要几分钟才能完成,它通过使用异步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一点一滴客户端...这适用于synchronious要求,我会看到,如果一个XMLHttpRequest得到了readystatechange每条线的事件。

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

相反,为什么重新发明一个单独的线程池时,IIS已经为你做了这个。

+0

回答重新发明线程池...对于长时间运行的进程,不建议使用线程池。 http://msdn.microsoft.com/en-us/magazine/cc164128.aspx – Keltex 2009-03-05 23:46:39

回答

1

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

如果作业很重要,可能会有问题需要考虑,例如缓解工作进程回收中间作业或保存作业状态以便重新启动作业。如果作业非常关键,最好编写一个执行作业的Windows服务,并使用Remoting或其他来查询进度。

0
  1. 可以改变web.config中的请求超时值,财产以后这样的: <configuration> <system.web><httpRuntime executionTimeout="1000" /></system.web></configuration>

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

0

这里有一个想法...

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

您的第一个AJAX请求是启动该进程。随后的调用将获得包括%完成的过程的状态。使用计时器来轮询(每隔几秒或任何似乎最好的工作)以完成%,直到全部完成为止。

AJAX请求(XmlHttpRequest)在客户端本身没有超时(http://luke.breuer.com/tutorial/xmlhttprequest.aspx ...向下滚动到超时),但我认为这不是一个好主意让他们在几分钟内完成工作如果可能的话:

+0

单独的线程仍然存在于工作进程中。 – 2009-03-05 23:30:43

+0

我纠正了一个错字。 – Keltex 2009-03-05 23:42:09

0

根据定义HTTP请求是无状态的。正如其他人指出的那样 - 你无法预测IIS什么时候会回收这个过程。

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

0

为了什么它的价值,

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

作品就好了。