如何正确使用NetMq Poller接收数据

时间:2018-11-29 14:44:52

标签: c# .net wpf netmq

我被赋予创建一个接口的任务,我可以通过该接口从发送方通过套接字接收数据,为此,我在发送方使用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

1 个答案:

答案 0 :(得分:0)

  1. 首先,最好在ReceiverService中创建一个类似于ActorModel的任务,因为最后如果您想在任何地方重用它,则需要记住您应该首先创建一个Task。
  2. 始终在using语句中插入套接字会很好,因为如果不使用套接字,则应始终关闭套接字
 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();
     }
 }