2011-03-22 98 views
1
List<string> urls = this.populateRequestList(); 

this.Logger("Starting"); 

var reqs = urls.Select<string, WebRequest>(HttpWebRequest.Create).ToArray(); 
var iars = reqs.Select(req => req.BeginGetResponse(null, null)).ToArray(); 
var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray(); 

this.Logger("Done"); 

事情,我注意到迄今:
當我運行此代碼,「啓動」在我的日誌顯示出來,但「完成」一直沒有出現。當我在調試器中查看整個過程時,它似乎跳過它,就像它甚至不在那裏一樣。也沒有例外。當reqs.Select正在循環通過req.EndGetResponse(iars[i])時,它就像凍結或跳過內容。當我在調試器中查看它時,在跳到結尾之前我沒有超過10-15個循環。C#異步Http請求,如何停止跳過?

問題:
如何從期間var rsps = reqs.Select((req, i) => req.EndGetResponse(iars[i])).ToArray(); 「跳過」 某個時候停止?

如何從rsps獲取html?我認爲這個問題是由「跳過」造成的。我試着循環回答每個回覆,並呼籲Repsponse.GetResponseStream()等等,但只要它跳過,就沒有任何反應。

回答

7

與您的代碼的問題是,BeginGetResponse(NULL,NULL)接受回調的操作完成時被調用的第一個參數。該回調是應該調用EndGetResponse的地方。當您調用EndGetResponse時,操作尚未完成。

看看這篇文章,看看如何使用迭代器在C#中完成異步Web請求:http://tomasp.net/blog/csharp-async.aspx

如果使用任務並行庫或.NET 4,你也可以這樣做:

var urls = new List<string>(); 

      var tasks = urls.Select(url => 
       { 
        var request = WebRequest.Create(url); 
        var task = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); 
        task.Start(); 
        return task; 
       }).ToArray(); 

      Task.WaitAll(tasks); 

      foreach (var task in tasks) 
      { 
       using (var response = task.Result) 
       using (var stream = response.GetResponseStream()) 
       using (var reader = new StreamReader(stream)) 
       { 
        var html = reader.ReadToEnd(); 
       }         
      } 
+0

啊,那是關鍵,謝謝。直到我讀到你在這裏所說的回調函數之前,我一直很難遵循異步的例子。在一個側面說明中,我無法完全測試你的代碼,因爲它拋出了一個有關task.Start()無法用null做某事的異常。 – PiZzL3 2011-03-23 01:01:29

+0

這是[完全正常](http://msdn.microsoft.com/en-us/library/ms228967.aspx)調用'End *'來(同步)等待異步操作完成。對「啓動」的調用是不必要的。 'FromAsync'返回一個已經啓動的'Task'。 – 2011-08-23 01:36:05

+0

task.Start()將在給定示例中導致異常,因爲Task.FromAsync會爲您啓動任務。 – Restuta 2012-06-30 23:29:56

0

您正嘗試使用異步請求方法執行同步請求,但這不起作用。

您應該使用BeginGetResponse以處理每個響應的回調方法啓動請求。如果您在BeginGetResponse之後立即致電EndGetResponse,它將失敗,因爲響應尚未開始到達。

如果要製作同步請求,請改爲使用GetResponse方法。

+0

這是[完全正常(http://msdn.microsoft.com/en-us/library/ms228967。 aspx)調用'End *'來(同步)等待異步操作完成。 – 2011-08-23 01:35:30