Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly use NetMq Poller for Receiving data

Tags:

c#

.net

wpf

netmq

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

like image 504
user167124 Avatar asked Nov 07 '22 23:11

user167124


1 Answers

  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();
     }
 }
like image 114
bzyku Avatar answered Nov 14 '22 21:11

bzyku