【问题标题】:How to read all the items from the Channel when you don't know their actual count当您不知道它们的实际数量时如何从 Channel 中读取所有项目
【发布时间】:2019-09-10 12:15:20
【问题描述】:

我正在尝试实现一个爬虫,它访问某个 URL,从中收集新的相对 URL 并构建一个报告。我正在尝试同时使用 Crystal 光纤和通道,如下所示:

urls = [...] # of String
visited_urls = []

pool_size.times do
  spawn do
    loop do
      url = urls.shift?
      break if url.nil?

      channel.send(url) if some_condition
    end
  end
end

# TODO: here the problem!
loop do
  url = channel.receive?
  break if url.nil? || channel.closed?

  visited_urls << url
end

puts visited_urls.inspect

但是在这里我有一个问题 - 无限秒 loop(它调用 channel.receive? 直到频道中的最后一个项目,然后等待一条永远不会到达的新消息)。存在问题是因为我不知道频道中实际有多少项目,所以我不能像 Crystal lang 指南的 Concurency 部分中建议的那样做。

所以,当我们不知道它会存储多少物品并且我们需要接收多少物品时,也许有一些好的做法如何与渠道合作?谢谢!

【问题讨论】:

    标签: concurrency crystal-lang


    【解决方案1】:

    一个常见的解决方案是设置一个 kill 值。作为主要数据流的一部分,如下所示:

    results = Channel(String|Symbol).new(POOL_SIZE * 2)
    
    POOL_SIZE.times do
      spawn do
        while has_work?
          results.send "some work result"
        end
    
        results.send :done
      end
    end
    
    done_workers = 0
    
    loop do
      message = results.receive
      if message == :done
        done_workers += 1
        break if done_workers == POOL_SIZE
      elsif message.is_a? String
        puts "Got: #{message}"
      end
    end
    

    或通过辅助渠道发出事件信号:

    results = Channel(String).new(POOL_SIZE * 2)
    done = Channel(Nil).new(POOL_SIZE)
    
    POOL_SIZE.times do
      spawn do
        while has_work?
          results.send "some work result"
        end
    
        done.send nil
      end
    end
    
    done_workers = 0
    loop do
      select
      when message = results.receive
        puts "Got: #{message}"
      when done.receive
        done_workers += 1
        break if done_workers == POOL_SIZE
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多