2009-03-05 28 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. 
} 

作品就好了。