[英]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.