【问题标题】:How to correctly use NetMq Poller for Receiving data如何正确使用 NetMq Poller 接收数据
【发布时间】:2019-02-11 19:12:36
【问题描述】:

我被赋予创建一个接口的任务,我通过套接字从发送方接收数据,为此我在发送方使用 NetMQ PushSocket,然后我在客户端接收数据 sung PullSocket,我必须收到数据时更新 UI(WPF 应用程序),因此当我在单独的服务类中执行此操作并在 UI ViewModel 中调用该类时,我在 PullSocket 的 ReceiveReady 事件中使用轮询器接收数据,UI 线程挂起,所以我使用 Poller.Run在一个任务中,现在的问题是,当我停止轮询然后重新启动它时,它不会调用 ReceiveReady 事件

这里是接收数据的ReceiverService。

public class ReceiverService
{
    string msg;
    string _address;
    int _port;
    PullSocket receiver;
    NetMQPoller poller;
    private MapViewModel ViewModel { get; set; }
    public ReceiverService(MapViewModel mapViewModel, int port = 5555)
    {
        _address = GetComputerLanIP();
        _port = port;
        receiver = new PullSocket($"tcp://{_address}:{_port}");
        receiver.Options.Linger = TimeSpan.Zero;             
        this.ViewModel = mapViewModel;
        poller = new NetMQPoller { receiver };
        receiver.ReceiveReady += receiver_ReceiveReady;
    }
    public void Start()
    {
        receiver.Connect($"tcp://{_address}:{_port}");
        poller.Run();
    }
    public void Stop()
    {
        receiver.Disconnect($"tcp://{_address}:{_port}");
        poller.Stop();
    }

    private void receiver_ReceiveReady(object sender, NetMQSocketEventArgs e)
    {
        // receive won't block as a message is ready
        msg = e.Socket.ReceiveFrameString();
        // send a response
        if (!string.IsNullOrEmpty(msg))
        {
            try
            {
              //Updaing the ViewModel here
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }
    }
    private string GetComputerLanIP()
    {
        string strHostName = Dns.GetHostName();
        IPHostEntry ipEntry = Dns.GetHostEntry(strHostName);

        foreach (var ipAddress in ipEntry.AddressList)
        {
            if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
            {
                return ipAddress.ToString();
            }
        }
        return "";
    }
    private string GetValueFromMessage(string identifier)
    {
        msg.Replace("{", "");
        msg.Replace("}", "");
        identifier = /*" " + */identifier + " = ";
        try
        {
            int index = msg.IndexOf(identifier) + identifier.Length;

            if (index != -1)
            {
                int index2 = msg.IndexOf(";", index);
                if (index2 == -1)
                {
                    index2 = msg.Length;
                }
                return msg.Substring(index, index2 - index);
            }
        }
        catch (IndexOutOfRangeException ex)
        {
            return null;
        }
        return null;
    }
}

在我的 ViewModel 中,我为这些设置了命令

private void StartReceiver()
    {
     Task.Run(() => ReceiverService.Start());           
    }
private void StopReceiver()
    {           
     Task.Run(() => ReceiverService.Stop());                         
    }

我做错了什么?我是 NetMQ 和 WPF 的新手。 TIA

【问题讨论】:

  • 我不确定轮询器是否支持重新启动...尝试在每次停止后重新创建轮询器。无论如何,轮询器被设计为永远运行,通常在您想退出应用程序时停止它。
  • 另外,在只有一个套接字的情况下,您实际上并不需要轮询器。只需拨打接收电话。

标签: c# .net wpf netmq


【解决方案1】:
  1. 一开始最好在 ReceiverService 中创建一个任务,类似于 ActorModel,因为最后如果您想在任何地方重用它,您需要记住您应该首先创建一个任务。
  2. 总是在 using 语句中有 socket 会很好,因为如果你不使用它,你应该总是关闭它
 public async Task StartAsync()        {
     await Task.Run(() => ThreadBody())
 }
 public void Stop()
 {
     _poller.Stop();
 }
     private void ThreadBody()
 {
     using (PullSocket receiverSocket = new PullSocket())
     using (_poller = new NetMQPoller())
     {
         receiverSocket.Connect($"tcp://{_address}:{_port}");
         receiverSocket.ReceiveReady += receiver_ReceiveReady;
         _poller.Add(receiverSocket);
         _poller.Run();
     }
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 2022-01-05
    • 2021-11-11
    • 2019-02-17
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多