WEB开发网
开发学院软件开发C语言 适合C# Actor的消息执行方式(5):一个简单的网络... 阅读

适合C# Actor的消息执行方式(5):一个简单的网络爬虫

 2010-09-30 20:50:14 来源:WEB开发网   
核心提示: 缺陷这里的缺陷是什么?其实很明显,您发现了吗?使用Actor模型可以保证消息执行的线程安全,适合C# Actor的消息执行方式(5):一个简单的网络爬虫(6),不过很明显Start方法并非如此,我们只能用它来“开启”一个抓取任务,但是我们现在做不到啊,嗯,但是如果我们想再

缺陷

这里的缺陷是什么?其实很明显,您发现了吗?

使用Actor模型可以保证消息执行的线程安全,不过很明显Start方法并非如此,我们只能用它来“开启”一个抓取任务。但是如果我们想再次“手动”提交一个需要抓取的URL怎么办?所以理想的方法,其实也应该是向Monitor发送一个消息来启动第一个URL抓取任务。需要补充,则发送多个URL即可。可是,这个消息定义在什么地方才合适呢?我们的Monitor类已经实现了Actor<Action<ICrawlResponseHandler>>,已经没有办法接受另一个接口作为消息了,不是吗?

这就是一个致命的限制:一个Actor虽然可以实现多个接口,但只能接受其中一个作为消息。同样的,如果我们要为Monitor提供其他功能,例如“查询”某个URL的抓取状态,也因为同样的原因而无法实现。还有,便是在前几篇文章中谈到的问题了。Crawler和Monitor直接耦合,我们向Crawler发送的消息只能携带一个Monitor对象。

最后,便是一个略显特别的问题了。我们这里使用WebClient的DownloadString方法来获取网页的内容,但是这是个同步IO操作,理想的做法中我们应该使用异步的方法。所以,我们可以这么写:

void ICrawlRequestHandler.Crawl(Monitor monitor, string url) 
{ 
  WebClient webClient = new WebClient(); 
  webClient.DownloadStringCompleted += (sender, e) => 
  { 
    if (e.Error == null) 
    { 
      var matches = Regex.Matches(e.Result, @"href=""(http://[^""]+)""").Cast<Match>(); 
      var links = matches.Select(m => m.Groups[1].Value).Distinct().ToList(); 
      monitor.Post(m => m.Succeeded(this, url, links)); 
    } 
    else 
    { 
      monitor.Post(m => m.Failed(this, url, e.Error)); 
    } 
  }; 
  webClient.DownloadStringAsync(new Uri(url)); 
} 

如果您还记得老赵在最近一篇文章中关于IO线程池的讨论,就可以了解到DownloadStringCompleted事件的处理方法会在统一的IO线程池中运行,这样我们无法控制其运算能力。因此,我们应该在回调函数中向Crawler自己发送一条消息表示抓取完毕……呃,但是我们现在做不到啊。

嗯,下次再说吧。

出处:http://www.cnblogs.com/JeffreyZhao/archive/2009/07/27/message-execution-model-for-c-sharp-actor-5-a-simple-web-crawler.html

本文完整代码:http://gist.github.com/154815

上一页  1 2 3 4 5 6 

Tags:适合 Actor 消息

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接