简体   繁体   中英

How do I properly dispose a SimpleRpcServer object?

I have a RabbitMQ SimpleRpcServer and I want to know how to properly dispose it when I'm done with it. The pattern has a main loop that blocks until it receives a message, handles the messages, and then blocks again. This means that in order to break the loop, I have to send a specially-coded message that the handler can use to break out of the loop.

I've read that RabbitMQ channels should be accessed from the same thread that created them. If this is true (I can't find a source), does this mean that to dispose my SimpleRpcServer, I'll have to create a new channel specifically to send the close message to the main loop?

Here's pseudo code:

Main Loop ( actual code here ):

//I run this on a ThreadPool thread
foreach (var evt in m_subscription) //blocks until a message appears
{
    ProcessRequest(evt);
}

Handler:

private void ProcessRequest(evt)
{
    if(evt.BasicProperties.ContentType == "close") //close flag
    {
        base.Close();
    }
    else
    {
        //process message
    }
}

Disposal code (Creates a new channel specifically for canceling the main loop):

//I call this from the main thread
public void Dipose()
{
    var channel = new Channel();
    var props = new Properties("close"); //close flag
    channel.BasicPublish(queueName, props);
    channel.Dispose();
}

Note that I left out some initialization and disposal code. I know that this code won't compile.

Yes you shouldn't share the channel between two or more threads, read here http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/v3.2.4/rabbitmq-dotnet-client-3.2.4-user-guide.pdf “2.10. IModel should not be shared between threads”

To close your channel you could create a thread with the subscription using the channel then close the channel on the main thread, as:

Init the connection, channel etc...

ConnectionFactory connection_factory = new ConnectionFactory();
        IConnection conn = null;
        IModel channel = null;
        Subscription sub = null;
        private void Connect()
            try
            {
                conn = connection_factory.CreateConnection();
                channel = conn.CreateModel();
                sub = new Subscription(channel, your_queue, true);
                StartSubscribeThread (sub);
….

Create your thread:

 public void  StartSubscribeThread(Subscription sub)
 {
    var t = new Thread(() => InternalStartSubscriber(sub));
    t.Start();
 }



private void InternalStartSubscriber(Subscription sub)
{
   foreach (BasicDeliverEventArgs e in sub)
   {
    //Handle your messages 
   }
} 

And finally:

private void Disconnet()
sub.Close();
channel.Close();
channel.Dispose();

In this way you can avoid to create another channel to close the first-one

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM