0

I need to poll multiple TCP servers (embedded hardware) continuously from multiple Android devices using Xamarin.Android and then update UI accordingly. Also, these Android devices can interact with the servers and change settings. I have used a queue to manage the synchronous polling as well asynchronous commands from these multiple devices (not shown in below code).

What I have now is a poor synchronous implementation which sometimes blocks UI or overloads garbage collection. Couldn't find any resource related to my query. Need guidance on the best way to go about it.

BlockingCollection<string[]> tcp_Queue = new BlockingCollection<string[]>();
CancellationTokenSource cts = new CancellationTokenSource();
ThreadPool.QueueUserWorkItem(o => TCP_Communicator());
ThreadPool.QueueUserWorkItem(o => ScanServers());
...
void ScanServers()
        {
            while (true)
            {
                while (datasync)
                {
                    if (haltscan)
                    {
                        break;
                    }
                    if (tcp_Queue.Count == 0)
                    {
                        for (int i = 0; i < ips.Length; i++)
                        {
                            if (Array.IndexOf(unreachable_IPs, ips[i]) == -1)
                            {
                                tcp_Queue.Add(new string[] { ips[i], query_command });
                            }
                        }
                    }
                }
            }
        }


void TCP_Communicator()
        {            
            while (true)
            {
                while (datasync)
                {
                    try
                    {
                        string[] tcp_data = tcp_Queue.Take(cts.Token); // A queue containing the IPs and command frame
                        using (var tcpClient = new TcpClient())
                        {
                            try
                            {
                                tcpClient.SendTimeout = 1000;
                                tcpClient.ReceiveTimeout = 1000;
                                tcpClient.NoDelay = true;
                                tcpClient.Connect(tcp_data[0], 80);
                                using (var networkStream = tcpClient.GetStream())
                                {
                                    Log.Verbose(tag, "Ping Success: " + tcp_data[0]);
                                    try
                                    {
                                        byte[] data = Encoding.ASCII.GetBytes(tcp_data[1]);
                                        networkStream.Write(data, 0, data.Length);
                                        Log.Verbose(tag, "Command: {0}", tcp_data[1]);
                                        byte[] new_data = new byte[45];
                                        int bytes = networkStream.Read(new_data, 0, new_data.Length);
                                        responseData = Encoding.ASCII.GetString(new_data, 0, bytes);
                                        Log.Verbose(tag, "Response: {0}", responseData);                                        
                                    }
                                    catch (TimeoutException)
                                    {
                                        Console.WriteLine("TimeoutException");
                                        responseData = string.Empty;
                                    }
                                    catch (IOException e)
                                    {
                                        Console.WriteLine("IOException" + e);
                                        responseData = string.Empty;
                                    }
                                }
                            }
                            catch (SocketException)
                            {
                                Log.Verbose(tag, "Ping Timeout: " + tcp_data[0]);
                                responseData = string.Empty;                             
                            }
                        }                      
                        Check_ScanResults(tcp_data, responseData);
                    }
                    catch (System.OperationCanceledException)
                    {
                    }
                }
            }
        }

Bilal Kazi
  • 126
  • 1
  • 11
  • Hey bilal! You should be able to just look for any C# example of polling, like this one https://stackoverflow.com/questions/23340894/polling-the-right-way – Saamer Nov 13 '19 at 22:40
  • @Saamer Thanks. That certainly helped me with the polling part. However, I also have to deal with asynchronous inputs from users and hence I have to use blocking queues to manage both type of requests to the server. How do I manage both in polling – Bilal Kazi Nov 18 '19 at 08:31

0 Answers0