c# - 当我尝试处理轮询器时,NetMQ 卡住了(请求-回复模式)
问题描述
这是我第一个使用 NetMQ (ZMQ) 框架的项目,所以,也许我不明白如何准确地使用它。
我创建了一个包含两个应用程序的 Windows 窗体项目,一个向另一个发送“ping”并接收“pong”作为答案。该协议并不那么复杂,并且使用请求-回复模式,所有命令都有一个标识目标的第一部分,如“查询”或“通知”,第二部分包含命令或消息本身。在这种情况下,一个应用程序发送一个“query-ping”,另一个应用程序发送一个“inform-pong”。
我创建了一个类来封装所有脏活,这样主窗体就可以非常简单地使用协议。一切正常,但是当我尝试关闭应用程序时,它卡在轮询器中并且应用程序永远不会关闭。在 Visual Studio 中,我可以看到暂停和停止按钮,但没有出现任何异常或错误:
当我单击暂停按钮时,我收到此消息(应用程序处于中断模式):
如果我单击“继续执行”,应用程序将返回相同状态并且永远不会关闭。
如果我删除轮询器,应用程序将正常关闭,但当然,轮询器不起作用,应用程序不再应答。
这是来自 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 类的代码。它位于一个单独的库项目中。在我的 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";
}
}
}
解决方案
您可以尝试调用 NetMQConfig.Cleanup(); 在窗口关闭事件中?
推荐阅读
- javascript - 使用 jQuery 从 2 个不同的来源填充数据表
- arrays - 我正在尝试将 2 个总和从子例程传递回 C 中的主函数
- python-3.x - 如何将类实例及其所做的一切传递给 Python 中的另一个类
- r - 如何从数据框中获取数组
- visual-studio-code - VSCode Rego Plugin opa 评估未按预期工作
- php - 如何有效地跨多个类传递一组设置值
- reactjs - 创建全日历反应 :: 错误 dateProfileGenerator 未定义
- c++ - 我正在使用快速排序对数组进行排序。但是我让数组未排序。我试图找到错误但失败了
- javascript - 使用 javascript/moment 将日期格式化为所需格式
- python - 如何使用 python-telegram-bot 发送消息