我很难学习Fibers \ coroutines背后的想法以及Crystal中的实现。
我希望这是一个正确的地方,我会完全接受一个"不在这里"回答:)
这是我在Ruby中处理多线程的常用方法:
=IF(AND(ISERROR(FIND("ø";B2));ISERROR(FIND(CHAR(34);B2)));B2;IF(ISERROR(FIND("ø";B2));LEFT(B2;FIND(CHAR(34);B2)-1); LEFT(B2; FIND("ø";B2)-1)))
这样我打开一个新线程,通常是传入连接或其他东西,将线程添加到线程数组,然后检查我没有更多线程,然后我想要的。
使用spawn \ channels \ fiber等在Crystal中实现类似的东西会有什么好方法。?
答案 0 :(得分:14)
这样的事情:
require "socket"
ch = Channel(TCPSocket).new
10.times do
spawn do
loop do
socket = ch.receive
socket.puts "Hi!"
socket.close
end
end
end
server = TCPServer.new(1234)
loop do
socket = server.accept
ch.send socket
end
此代码将预生成10根光纤以参加请求。该通道是无缓冲的,因此如果它们不能被任何光纤接收,则连接将不会排队。
答案 1 :(得分:6)
您无法复制其对线程的工作方式。 spawn
不会返回协程对象,并且无法join
协程。
然而,我们可以在协同程序和池管理器之间建立通道。这个经理可以在它自己的协程中运行,也可以作为主协程 - 这将阻止进程退出。
这是一个工作示例,使用worker(&block)
方法生成协程,并打开通道以返回其状态(失败或终止),以及将保留的pool(&block)
方法一群这样的工人,从结果渠道中读取以了解协同程序的状态,并继续产生新的协同程序。
def worker(&block)
result = UnbufferedChannel(Exception?).new
::spawn do
begin
block.call
rescue ex
result.send(ex)
else
result.send(nil)
end
end
result
end
def pool(size, &block)
counter = 0
results = [] of UnbufferedChannel(Exception?)
loop do
while counter < size
counter += 1
puts "spawning worker"
results << worker(&block)
end
result = Channel.select(results)
counter -= 1
results.delete(result)
if ex = result.receive
puts "ERROR: #{ex.message}"
else
puts "worker terminated"
end
end
end
pool(5) do
loop { helper_method(1, 2, 3, 4) }
end