Как правильно использовать NetMq Poller для получения данных - PullRequest
0 голосов
/ 29 ноября 2018

Мне было дано задание создать интерфейс, где я получаю данные через сокет от отправителя, для этого я использую NetMQ PushSocket для стороны отправителя, а затем я получаю данные на стороне клиента в исполнении PullSocket, и я долженобновлять пользовательский интерфейс (приложение WPF) при получении данных, чтобы я получал данные с помощью программы poller в событии ReceiveReady объекта PullSocket, когда я делаю это в отдельном классе обслуживания, и вызываю этот класс в пользовательской интерфейсе ViewModel, когда поток пользовательского интерфейса зависает, поэтому я использую 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.ТИА

1 Ответ

0 голосов
/ 11 февраля 2019
  1. сначала было бы хорошо выполнить задачу внутри ReceiverService, своего рода ActorModel, потому что, в конце концов, если вы хотите использовать ее где-либо еще, вам нужно помнить, что вы должны сначала создать задачу.
  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();
     }
 }
...