问题
In my ruby script,I am using celluloid-zmq gem. where I am trying to run evaluate_response asynchronously inside pollers using,
async.evaluate_response(socket.read_multipart)
But if I remove sleep from loop, somehow thats not working out, It is not reaching to "evaluate_response" method. But if I put sleep inside loop it works perfectly.
require 'celluloid/zmq'
Celluloid::ZMQ.init
module Celluloid
module ZMQ
class Socket
def socket
@socket
end
end
end
end
class Indefinite
include Celluloid::ZMQ
## Readers
attr_reader :dealersock,:pullsock,:pollers
def initialize
prepare_dealersock and prepare_pullsock and prepare_pollers
end
## prepare DEALER SOCK
def prepare_dealersock
@dealersock = DealerSocket.new
@dealersock.identity = "IDENTITY"
@dealersock.connect("tcp://localhost:20482")
end
## prepare PULL SOCK
def prepare_pullsock
@pullsock = PullSocket.new
@pullsock.connect("tcp://localhost:20483")
end
## prepare the Pollers
def prepare_pollers
@pollers = ZMQ::Poller.new
@pollers.register_readable(dealersock.socket)
@pollers.register_readable(pullsock.socket)
end
def run!
loop do
pollers.poll ## this is blocking operation never mind though we need it
pollers.readables.each do |socket|
## we know socket.read_multipart is blocking call this would give celluloid the chance to run other process in mean time.
async.evaluate_response(socket.read_multipart)
end
## If you remove the sleep the async evaluate response would never be executed.
## sleep 0.2
end
end
def evaluate_response(message)
## Hmmm, the code just not reaches over here
puts "got message: #{message}"
...
...
...
...
end
end
## Code is invoked like this
Indefinite.new.run!
Any idea why this is happening?
回答1:
The question was 100% changed, so my previous answer does not help. Now, the issues are...
ZMQ::Poller
is not part of Celluloid::ZMQ
You are directly using the ffi-rzmq
bindings, and not using the Celluloid::ZMQ
wrapping, which provides evented & threaded handling of the socket(s).
It would be best to make multiple actors -- one per socket -- or to just use Celluloid::ZMQ
directly in one actor, rather than undermining it.
Your actor never gets time to work with the response
This part makes it a duplicate of:
- Celluloid async inside ruby blocks does not work
The best answer is to use
after
orevery
and notloop
... which is dominating your actor.
You need to either:
- Move
evaluate_response
to another actor. - Move each socket to their own actor.
This code needs to be broken up into several actors to work properly, with a main sleep
at the end of the program. But before all that, try using after
or every
instead of loop
.
来源:https://stackoverflow.com/questions/32479871/running-code-asynchronously-inside-pollers