2010-10-24 44 views
0

我有一個從遠程站點檢索html並解析它的過程。我將幾個URL傳遞到方法中,所以我希望每次URL完成解析時都會調整進程併發出屏幕通知。例如,這就是我想要做的事:帶有活動界面進度狀態的Ajax服務器進程?

List<string> urls = ...//load up with arbitary # of urls 

foreach (var url in urls) 
{ 
    string html = GetContent(url); 
    //DO SOMETHING 
    //COMPLETED.. SEND NOTIFICATION TO SCREEN (HOW DO I DO THIS) 
} 

public static string GetContent(string url) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
    request.Method = "GET"; 

    using (var stream = request.GetResponse().GetResponseStream()) 
    { 
     using (var reader = new StreamReader(stream, Encoding.UTF8)) 
     { 
      return reader.ReadToEnd(); 
     } 
    } 
} 

在循環每次迭代中,我要顯示的URL已經完成,並移動到下一個。我怎樣才能做到這一點?

回答

1

您需要擔心的第一件事是(我假設)您正在ASP.NET代碼中運行潛在的長時間運行的操作。當您運行IIS超時時,這會成爲問題。 (默認爲90秒。)假設您正在處理10個網址,每個網址需要15秒才能完成reader.ReadToEnd() –您的代碼將超時並在第六個網址後被殺。

你可能會想:「我可以加快超時」,但這不是一個好的答案;你仍然處於時間壓力之下。

我解決這類問題的方法是將長時間運行的操作移動到獨立的Windows服務中,然後使用WCF在ASP.NET代碼和服務之間進行通信。該服務可以運行一個線程池來執行處理一組URL的請求。 (Here's an implementation,它允許您排隊工作項目。)

現在,從您的網頁,您可以通過AJAX請求輪詢狀態更新。 ASP.NET代碼中的處理程序可以使用WCF從服務進程中提取狀態信息。

執行此操作的一種方法可能是爲每個提交的工作單元分配一個唯一的ID並將該ID返回給客戶端。然後,客戶端可以通過發送工作單元狀態的AJAX請求輪詢狀態n。在服務中,保留工作單元的List及其狀態(適當時爲lock以避免併發問題)。

public class WorkUnit { 
    public int ID { get; set; } 
    public List<string> URLs { get; set; } 
    public int Processed { get; set; } 
} 

 

private var workUnits = new List<WorkUnit>(); 

private void ExecuteWorkUnit(int id) { 
    var unit = GetWorkUnit(id); 

    foreach (var url in unit.URLs) { 
     string html = GetContent(url); 
     // do whatever else... 
     lock (workUnits) unit.Processed++; 
    } 
} 

public WorkUnit GetWorkUnit(int id) { 
    lock (workUnits) { 
     // Left as an exercise for the reader 
    } 
} 

你需要填寫方法來添加一個工作單位,返回給定的工作單元的狀態,並處理線程池。

我已經使用了一個類似的體系結構,取得了巨大的成功。