2011-12-23 64 views
0

我正在使用WebClient類和我自己的薄包裝器來請求JSON over HTML - 我在Comet-like體系結構的接收端,因此客戶端需要始終保持待處理請求的打開狀態,以便服務器可以隨意推送給客戶端。如何在超時或響應後不斷打開WebClient請求

我想確認下面的代碼是否有必要做一個正確的和安全的方式:

 subscriber = new Action(() => 
     { 
      // This function wraps the WebClient 'DownloadStringAsync' method 
      client.BeginDownload(this.Path, new AsyncCallback(x => 
      { 
       var data = (x.AsyncState as Func<JsonResponse>).EndInvoke(x); 
       if (data != null) 
       { 
        OnReceive(data, new Uri(this.FullUri)); 
       } 
       subscriber(); // Received data so re-submit request 

      }), this.QueryArgs); 

      while (client.IsBusy)// As long as busy, no need to re-submit a request 
      { 
      } 
      subscriber(); 
     }); 

     subscriber(); 

從我自己的分析,它看起來對我來說,上面將確保客戶總是重新或者在a)收到答覆或b)超時時提交請求。這是一個可以接受的方式來達到這個目標嗎?還是有更好的做法,我錯過了?以這種方式使用while循環對我來說似乎並不標準,但我想不出任何其他方式來創建一個等待循環。

我也想確保我不會泄漏任何資源與此設置,因爲它可能會或可能不會保證EndInvoke()每次都被調用?

+0

這不會在技術上破壞任何東西,但while循環會將單個CPU內核旋轉到100%,直到發生故障。你應該在那裏有一個簡短的Thread.Sleep,即使它只有1ms。 –

+0

也許看看SignalR –

+0

正如Michael Yoon所說,爲了不讓CPU飽和,我會給出至少5ms的睡眠時間,然後再發送另一個請求。此外,我不會從服務器返回一段時間。這樣,我可以確保在等待期間獲得一些數據時,我立即用數據返回客戶端。 – Muthu

回答

1

我擔心遞歸調用最終會導致堆棧溢出。

如果你運行這個幾秒鐘,你會得到一個堆棧溢出錯誤...

Action<int> action = null; 
action = new Action<int>((i) => 
{ 
    Console.WriteLine("Hello {0}", i); 
    action(i+1); 
}); 
action(1); 

我到12181。你的距離有多遠? :)

從您的代碼的外觀看來,您似乎並不需要調用WebClient的Async方法。實際上,調用直接下載方法可能比您所使用的緊密循環更高效。

也許像這樣?

var uri = new Uri("http://www.google.com"); 
var client = new WebClient(); 
while(true) 
{ 
    try 
    { 
     var data = client.DownloadData(uri); 
     Console.WriteLine("Downloaded {0:N0} bytes.", data.Length); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 
} 
1

當我已經建立HTTP流媒體在過去的圖書館,我用了HttpWebRequest類,因爲它給你多一點控制。您可以在this code中找到一個示例,該示例與Twitter的HTTP Streaming API連接。