3

我使用来自http://fssnip.net/3K的代码创建了一个控制台程序。我发现

  1. 我要在末尾添加“System.Console.ReadLine() |> ignore”以等待线程完成。是否可以告诉所有 MailBoxProcessor 都已完成并且程序可以自行退出?

  2. 我试图将测试网址“www.google.com”更改为无效的网址,并得到以下输出。能否避免“输出竞赛”?

     代理 1 抓取的 http://www.google.co1m。  
     AgAAAent gent 3 完成。  
     绅士2完成了。  
     5 完成。  
     绅士4完成了。  
     代理 USupervisor RL 收集器完成。  
     已经完成了。  
     1 完成。

[编辑]

使用 Tomas 的更新http://fssnip.net/65后,最后的输出/爬网仍然终止。以下是我将“limit”改为5并添加一些调试信息后程序的输出。最后一行显示截断的 URL。这是一种检测所有爬虫是否完成执行的方法吗?

[Main] before crawl
[Crawl] before return result
http://news.google.com crawled by agent 1.
[supervisor] reached limit
http://www.gstatic.com/news/img/favicon.ico crawled by agent 5.
Agent 2 is done.
[supervisor] reached limit
Agent 5 is done.
http://www.google.com/imghp?hl=en&tab=ni crawled by agent 3.
[supervisor] reached limit
Agent 3 is done.
http://www.google.com/webhp?hl=en&tab=nw crawled by agent 4.
[supervisor] reached limit
Agent 4 is done.
http://news.google.com/n

我将主要代码更改为

printfn "[Main] before crawl"
crawl "http://news.google.com" 5
|> Async.RunSynchronously
printfn "[Main] after crawl"

但是,最后一个printfn "[Main] after crawl"永远不会执行,除非我在最后添加一个 Console.Readline() 。

[编辑 2]

代码在 fsi 下运行良好。但是,如果使用 fsi --use:Program.fs --exec --quiet 运行它也会有同样的问题

4

1 回答 1

5

我创建了一个片段,使用您询问的两个功能扩展了前一个片段:http: //fssnip.net/65

  1. 为了解决这个问题,我添加Start了带有AsyncReplyChannel<unit>. 当主管代理启动时,它会等待此消息并保存回复通道以供以后使用。完成后,它使用此通道发送回复。

    启动代理的函数返回等待回复的异步工作流。然后您可以调用crawlusing Async.RunSynchronously,这将在主管代理完成时完成。

  2. 为避免打印时出现竞争,您需要同步所有打印。最简单的方法是编写一个新代理:-)。代理接收字符串并将它们一一打印到输出(这样它们就不会被交错)。该片段隐藏了标准printfn函数,其中包含向代理发送字符串的新实现。

于 2011-07-02T13:16:10.050 回答