使用ZeroMQ QueueDevice(clrzmq)时,如何在C#中设置Linger套接字选项?

时间:2014-01-08 17:53:34

标签: c# multithreading linq sockets zeromq

我正在尝试修改ZeroMQ多线程服务示例(http://zguide.zeromq.org/cs:mtserver),以便套接字在关闭时无法无限期地延迟。 我无法弄清楚如何通过QueueDevice接口为两个套接字设置Linger值。在其他示例中,我只是为套接字设置“Linger”选项,当上下文关闭时,它们立即退出。在我当前的程序中,工作线程关闭,但主线程无限期挂起......这可能就像使用SetSocketOption一样简单,但我不理解这个方法的LINQ语法(还),而且“SocketOption”枚举不公开

注意:我正在使用Visual Studio 2013 Express与clrzmq的3.0.0-rc1通过NuGet使用以下命令获得:Install-Package clrzmq -Version 3.0.0-rc1

用法:启动程序并按“ENTER”告诉主线程关闭,然后等待工作人员关闭......但主线程将无限期阻塞。

这是我的代码(Program.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Threading;
// add ZeroMQ via NuGet like this: Install-Package clrzmq -Version 3.0.0-rc1
using ZeroMQ;
using ZeroMQ.Devices;   // for queuing

namespace MTServiceCS
{
    class ThreadContext
    {
        public ZmqContext _zmqContext = null;
        public int _threadID = 0;
    }

    class Program
    {
        public static bool g_keepRunning = false;

        public static void Main(string[] args)
        {
            Console.WriteLine("Starting MTServiceCS - multi-threaded hello-world - start the HelloWorld clients to test this server.");

            using (var context = ZmqContext.Create())
            {
                using (var queue = new ZeroMQ.Devices.QueueDevice(context, "tcp://*:5555", "inproc://workers", DeviceMode.Threaded))
                {
                    Console.WriteLine("Initializing Queue.");
                    queue.Initialize();
                    // TODO: how to set the "Linger" to zero?
                    // queue.BackendSetup.SetSocketOption(, 0);
                    // queue.FrontendSetup.SetSocketOption(, 0);

                    Console.WriteLine("Creating Threads.");
                    var workerThreads = new Thread[5];

                    // set to 'false' to tell the workers to shutdown
                    g_keepRunning = true;

                    for (int threadID = 0; threadID < workerThreads.Length; threadID++)
                    {
                        workerThreads[threadID] = new Thread(WorkerRoutine);
                        // passing in more than just the ZMQ Context
                        ThreadContext tc = new ThreadContext();
                        tc._threadID = threadID;
                        tc._zmqContext = context;

                        workerThreads[threadID].Start(tc);
                    }
                    Console.WriteLine("Threads created.");

                    Console.WriteLine("Starting Queue.");
                    queue.Start();

                    // we block here in the calling thread until "ENTER" is pressed and then try to shutdown...
                    Console.WriteLine("Press ENTER to shutdown.");
                    Console.ReadLine();

                    // tell the workers to exit, sleep and then exit... or die trying...
                    Console.WriteLine("Setting 'g_keepRunning' to false to tell workers to shutdown.");

                    g_keepRunning = false;
                    Console.WriteLine("HACK: Sleeping for 4 seconds to allow workers to exit");
                    Thread.Sleep(4000);

                    Console.WriteLine("Queue finished.");
                    queue.Stop();

                    Console.WriteLine("Stopping queue...");
                    if (queue.IsRunning)
                    {
                        Console.WriteLine("Queue is NOT running.");
                    }
                    else
                    {
                        while (queue.IsRunning)
                        {
                            Console.WriteLine("Queue is STILL running? Looping waiting for it to close...");
                            Thread.Sleep(1000);
                        }

                        Console.WriteLine("Queue has stopped running!");
                    }

                    Console.WriteLine("Queue stopped.");

                    queue.Close();
                    Console.WriteLine("Queue closed.");

                }
                Console.WriteLine("QueueDevice closed.");

                Console.WriteLine("Exiting context...");
            }

            Console.WriteLine("Press ENTER to exit.");
            Console.ReadLine();

        }   // Main

        private static void WorkerRoutine(object threadContext)
        {
            ThreadContext tc = (ThreadContext)threadContext;
            ZmqSocket receiver = tc._zmqContext.CreateSocket(SocketType.REP);

            // ZmqSocket receiver = ((ZmqContext)threadContext).CreateSocket(SocketType.REP);
            receiver.Connect("inproc://workers");
            Console.WriteLine("Thread# " + tc._threadID.ToString() + " starting.");
            // Console.WriteLine("Thread# starting.");

            // 1-second timeout
            TimeSpan tsTimeout = new TimeSpan(0, 0, 1);

            while (g_keepRunning)
            {
                string message = receiver.Receive(Encoding.Unicode, tsTimeout);

                if (message != null && message.Length > 0)
                {
                    Console.WriteLine("Message received: " + tc._threadID.ToString() + ": " + message);
                    Thread.Sleep(1000); // simulate our work here w/ a sleep for 1 second
                    // receiver.Send("World", Encoding.Unicode);
                    receiver.Send("World[" + tc._threadID.ToString() + "]", Encoding.Unicode);
                    // Console.WriteLine("Thread# " + tc._threadID.ToString() + " sending.");
                }
                else
                {
                    Console.WriteLine("No message received: " + tc._threadID.ToString());
                }
            }

            Console.WriteLine("Thread# " + tc._threadID.ToString() + " exiting.");
        }
    }
}

0 个答案:

没有答案