2010-09-27 36 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

相关问题