5

I have been given the task to create a interface where I receive data through socket from the sender, for this purpose I am using NetMQ PushSocket for the sender side and then I receive the data at client side sung PullSocket and I have to update the UI (WPF app) when data is received so I receive data using poller in ReceiveReady event of the PullSocket when I do this in a seperate service class and call that class in UI ViewModel the UI thread hangs, so I use Poller.Run in a task, now the problem is that when I stop the poller and then restart it again it doesn't call the ReceiveReady event

Here is the ReceiverService for receiving the data.

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;
    }
}

and in my ViewModel I have set commands for these

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

What am I doing wrong? I am new to NetMQ and WPF. TIA

user167124
  • 349
  • 2
  • 13
  • 1
    I'm not sure poller support restarting... Try to recreate the poller after every stop. Anyway, the poller is designed to run forever, usually you stop it when you want to quit the application. – somdoron Dec 02 '18 at 12:39
  • Also, in case of one socket, you don't really need poller. Just call receive. – somdoron Dec 02 '18 at 12:40

1 Answers1

2
  1. at first it would be good to make a task inside ReceiverService, kind of an ActorModel, because in the end if You would like to reuse it anywhere You need to remember that You should creat a Task first.
  2. always it would be good to have socket in using statement, because You should always close socket if You are not using it
 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();
     }
 }
canton7
  • 37,633
  • 3
  • 64
  • 77
bzyku
  • 120
  • 6