繁体   English   中英

当我尝试处理轮询器时,NetMQ 卡住了(请求-回复模式)

[英]NetMQ gets stuck when I try to dispose the Poller (Request-Reply pattern)

这是我第一个使用 NetMQ (ZMQ) 框架的项目,所以,也许我不明白如何准确地使用它。

我创建了一个带有两个应用程序的 Windows Forms 项目,一个向另一个应用程序发送“ping”并接收“pong”作为答案。 该协议并不那么复杂,并且使用请求-回复模式,所有命令都有一个标识目标的第一部分,如“查询”或“通知”,第二部分包含命令或消息本身。 在这种情况下,一个应用程序发送一个“query-ping”,另一个应用程序发送一个“inform-pong”。

我创建了一个 class 来封装所有脏活,这样主窗体就可以非常简单地使用协议。 一切正常,但是当我尝试关闭应用程序时,它卡在轮询器中并且应用程序永远不会关闭。 在 Visual Studio 中,我可以看到暂停和停止按钮,但没有出现任何异常或错误:

在此处输入图像描述

当我单击暂停按钮时,我收到此消息(应用程序处于中断模式):

在此处输入图像描述

如果我单击“继续执行”,应用程序将返回相同的 state 并且永远不会关闭。

如果我删除轮询器,应用程序将正常关闭,但当然,轮询器不起作用,应用程序不再应答。

这是来自 Form1 的代码:

using CommomLib;
using System;
using System.Windows.Forms;

namespace Test1
{
    public partial class Form1 : Form
    {

        ZmqCommunication zmqComm = new ZmqCommunication();
        int portNumber;
        string status;

        public Form1()
        {
            InitializeComponent();
            
            InitializeZmqComm();
        }

        public void InitializeZmqComm()
        {
            // Calls the ZMQ initialization.
            portNumber = zmqComm.InitializeComm();
            if (portNumber == 0)
                status = "Ini error";
            else
                status = "Ini ok";
        }

        // Executes a ping command.
        private void button1_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
            richTextBox1.AppendText(zmqComm.RequestPing(55001) + "\n");
        }


    }

}

这是来自我的 NetMQ class 的代码。 它位于一个单独的库项目中。 在我的 Dispose 方法中,我尝试了 Remove、Dispose 和 StopAsync 的所有组合,但没有任何效果:

using NetMQ;
using NetMQ.Sockets;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace CommomLib
{
    public class ZmqCommunication
    {
        ResponseSocket serverComm = new ResponseSocket();
        NetMQPoller serverPoller;

        int _portNumber;

        public ZmqCommunication()
        {
            _portNumber = 55000;
        }

        // Problem here! The serverPoller gets stuck. 
        public void Dispose()
        {
            //serverPoller.RemoveAndDispose(serverComm);
            //serverComm.Dispose();

            if (serverPoller.IsDisposed)
                Debug.WriteLine("A");

            //serverPoller.RemoveAndDispose(serverComm);
            serverPoller.Remove(serverComm);
            //serverPoller.StopAsync();
            serverPoller.Dispose();

            serverComm.Dispose();

            if (serverPoller.IsDisposed)
                Debug.WriteLine("B");

            Thread.Sleep(500);

            if (serverPoller.IsDisposed)
                Debug.WriteLine("C");

            Thread.Sleep(500);

            if (serverPoller.IsDisposed)
                Debug.WriteLine("D");

        }

        // ZMQ initialization.
        public int InitializeComm()
        {
            bool ok = true;
            bool tryAgain = true;

            // Looks for a port.
            while (tryAgain && ok)
            {
                try
                {
                    serverComm.Bind("tcp://127.0.0.1:" + _portNumber);
                    tryAgain = false;
                }
                catch (NetMQ.AddressAlreadyInUseException)
                {
                    _portNumber++;
                    tryAgain = true;
                }
                catch
                {
                    ok = false;
                }
            }

            if (!ok)
                return 0;   // Error.


            // Set up the pooler.
            serverPoller = new NetMQPoller { serverComm };
            serverComm.ReceiveReady += (s, a) =>
                {
                    RequestInterpreter();
                };

            // start polling (on this thread)
            serverPoller.RunAsync();

            return _portNumber;
        }

        // Message interpreter.
        private void RequestInterpreter()
        {

            List<string> message = new List<string>();

            if (serverComm.TryReceiveMultipartStrings(ref message, 2))
            {
                if (message[0].Contains("query"))
                {
                    // Received the command "ping" and answers with a "pong".
                    if (message[1].Contains("ping"))
                    {
                        serverComm.SendMoreFrame("inform").SendFrame("pong");
                    }

                }
            }

        }

        // Send the command "ping".
        public string RequestPing(int port)
        {

            using (var requester = new RequestSocket())
            {
                Debug.WriteLine("Running request port {0}", port);

                requester.Connect("tcp://127.0.0.1:" + port);

                List<string> msgResp = new List<string>();

                requester.SendMoreFrame("query").SendFrame("ping");

                if (requester.TryReceiveMultipartStrings(new TimeSpan(0, 0, 10), ref msgResp, 2))
                {
                    if (msgResp[0].Contains("inform"))
                    {
                        return msgResp[1];
                    }
                }

            }

            return "error";

        }


    }
}

放置一个断点,看看您是否甚至到达 ZmqCommunication.Dispose - 这可能是问题所在 - 表格 class 没有处理 ZmqCommunication class。

您可以尝试调用 NetMQConfig.Cleanup(); 在 window 关闭事件中?

感谢大家的回答,他们不是解决方案,而是为我指明了正确的方向。

经过大量调试,我发现这是一个愚蠢的问题。 我有两个几乎相同的程序(我都同时打开了),其中一个有 Dispose() 方法,另一个没有。 在调试过程中,在断点处,我以为我在一个程序中,但我在另一个程序中。 真的很傻。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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