2010-09-27 38 views
0

我有一段代碼,看起來像這樣:WebException不會在它應該出現的位置?

var task = Task.Factory.StartNew(() => 
{ 
    while (!bc.IsCompleted && !cts.Token.IsCancellationRequested) 
    { 
     PriorityDownloadPair pd; 
     if (bc.TryTake(out pd)) 
     { 
      var baseUri = pd.Value.Uri; 
      Console.WriteLine("({0}) {1}", pd.Key, baseUri.AbsoluteUri); 
      IEnumerable<HtmlNode> sq = null; 
      try 
      { 
       sq = SharpQuery.SharpQuery.Load(baseUri); 
      } 
      catch (WebException we) 
      { 
       Console.WriteLine(we.Message); 
       continue; 
      } 
      foreach (var node in sq.Find("a[href]")) 
      { 
       bc.Add(new PriorityDownloadPair(1, new DownloadItem { Uri = new Uri(baseUri, node.Attributes["href"].Value) })); 
      } 
     } 
    } 
}, cts.Token); 

它運行正常了一段時間(以下和下載每一個環節發現),直到它擊中404

404發生在我期望的SharpQuery.Load方法:

public static IEnumerable<HtmlNode> Load(Uri uri) 
{ 
    var doc = new HtmlDocument(); 
    WebClient wc = new WebClient(); 
    using (var str = wc.OpenRead(uri)) 
     doc.Load(str); 
    yield return doc.DocumentNode; 
} 

但是爲什麼我的try塊沒有捕獲它呢?

如果我去了它指向的調用堆棧這一行:

foreach (var node in sq.Find("a[href]")) 

sq.Find甚至不觸及任何網絡接口。這是怎麼回事?

這些線是同步的,

 using (var str = wc.OpenRead(uri)) 
      doc.Load(str); 

不是嗎?加載完成後不應該導致錯誤發生。

回答

1

這是因爲直到您實際讀取try塊後的數據纔會執行加載。

+0

因爲它是一個可枚舉的,呃?沒有意識到他們是這樣工作的。調用'.ToArray()'或其他東西會強制它評估,不是嗎? – mpen 2010-09-27 07:33:08

+0

是的,或者你可以將每個移動到try塊(如果這是訪問它) – 2010-09-27 07:40:12

+0

是的...... foreach是什麼導致訪問/評估,但我想我寧願趕上錯誤提前,它實際上正在發生,而不是在某個時候。這真的很瘋狂,但是你可以傳播這樣的錯誤。循環遍歷一個枚舉似乎應該是安全的。 – mpen 2010-09-27 07:46:56

相關問題