2012-05-21 33 views
0

我发现Rx框架看起来对于异步操作非常有用,但我无法理解如何使用它来下载大量页面。Web爬虫的Rx框架

我试图写这样的事情

var en = Enumerable.Range(0,100).Select(x => WebRequest.Create("http://google.com")).Select(x => Observable.FromAsyncPattern<WebResponse>(x.BeginGetResponse, 
    x.EndGetResponse)().Subscribe(r => Console.WriteLine(r.ContentLength))).ToList(); 

Ofcourse它不工作。如何做到这一点?

+0

你想在这里实现什么?什么是实际情况? Rx可能不是正确的方法 - 任务并行库可能就足够了。 – yamen

+0

@yamen在这个例子中,我只是试图异步下载100页。我询问了有关使用TPL执行此任务的问题,并且有人向我解释说,tpl适用于CPU绑定操作。对于I \ O操作,异步方法更好。 Rx使得异步方法很容易,对吧?当然,我可以做到没有Rx,但我想学习新的东西。 – Neir0

+0

合理 - 是VS 11还是.NET 4.5的选项? – yamen

回答

3

编辑:修改为提供简单的错误处理。

这里就是你需要做的:

var urls = new[] 
     { 
      "http://stackoverflow.com/questions/10693617/" 
        + "rx-framework-for-a-web-crawler", 
      "http://stackoverflow.com/", 
      "http://stackoverflow.com/users/259769/enigmativity", 
     }; 

Func<string, IObservable<WebResponse>> create = 
    url => 
     Observable.Defer(() => 
     { 
      var wr = WebRequest.Create(url); 
      return 
       Observable 
        .FromAsyncPattern<WebResponse>(
         wr.BeginGetResponse, 
         wr.EndGetResponse) 
        .Invoke() 
        .Catch(Observable.Return<WebResponse>(null)); 
     }); 

var query = 
    from u in urls.ToObservable() 
    from r in create(u) 
    select new 
    { 
     URL = u, 
     ContentLength = r == null ? -1L : r.ContentLength, 
    }; 

ServicePointManager.DefaultConnectionLimit = 100; 

query.Subscribe(x => Console.WriteLine(x)); 

我会更倾向于虽然提供比这更好的错误处理。我会派出一个包含异常的元组,而不仅仅是一个null的值。

+0

谢谢。但是,如果我有一个异常(如404)订阅刚停止工作。我怎么假装它? – Neir0

+0

@ Neir0 - 我添加了一些错误处理。 – Enigmativity