1

I have to connect, send and receive socket messages to a server. I have to implement the client application which is based on Windows Forms. (Target Framework: 4.5.1)

In five minute intervals I have to send a message to the server to keep the server online. (This is not a keep alive ping, this is a specified command to the server.)

I'd like to implement this task to keep the GUI live (not blocked), until the socket communication working in the background.

Everything is working fine, until one or more of the server are not available. The ConnectTaskAsync method wait (approximately 15 seconds) and send a "TIME OUT EXCEPTION". But this time to exception raised is a long time.

How is possible to call connect socket with 5 seconds timeout without blocking UI thread?

On Form load event, I create a timer

private void Form1_Load(object sender, EventArgs e)
{
        System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
        t.Interval = 1000;
        t.Tick += this.displayTimers;
        t.Start();
        System.Windows.Forms.Timer tKeepAlive = new System.Windows.Forms.Timer();
        tKeepAlive.Interval = 10000;
        tKeepAlive.Tick += clsKeepAlive.keepAlivePanelTimer;
        tKeepAlive.Start();
}

keepAlivePanelTimer is caller by timer

public async static void keepAlivePanelTimer(object sender, EventArgs e)
{
    List<clsPanelItem> panelList = (List<clsPanelItem>)((clsVmsGroup)actGroup).lstVmsItems;
    IEnumerator _idePanel = panelList.GetEnumerator();
    while (_idePanel.MoveNext())
    {
        clsPanelItem actPanel = (clsPanelItem)_idePanel.Current;
        try
        {
            //CancellationTokenSource cts = new CancellationTokenSource();
            await keepAlivePanel(actPanel);
        }
        catch (Exception _ex)
        {
            //Timeout Exceptions are handle here
            System.Diagnostics.Debug.Print("Err: " + _ex.Message + " - Panel: " + actPanel.ipAddress.ToString());
        }
        finally
        {

        }
    }
}

keepAlivePanel Async task called from timer

private static async Task keepAlivePanel(clsPanelItem actPanel, CancellationToken ct)
    {
        IPAddress ipAddress = actPanel.ipAddress;
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, app.vmsPanelCommPort);
        // Create a TCP/IP socket.
        Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.SendTimeout = 1000;      //Nothing was happened
        client.ReceiveTimeout = 1000;   //Nothing was happened
        await async45.ConnectTaskAsync(client, remoteEP, ipAddress, app.vmsPanelCommPort, ct);
}

ConnectTaskAsync connect to server

public static class async45
{
    public static Task ConnectTaskAsync(Socket socket, EndPoint endpoint, IPAddress ip, int port, CancellationToken ct)
    {
        Task t = Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, endpoint, null);
        return t;
    }
}

Another methods to use send and receive bytes

public static Task SendTaskAsync(this Socket socket, byte[] buffer)
    {
        return Task.Factory.FromAsync<int>(
                        socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, socket),
                        socket.EndSend);
    }

    public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
    {
        return Task.Factory.FromAsync<int>(
                        socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
                        socket.EndReceive);
    }

I tried different things with less success.

//    var timeoutTask = Task.Delay(TimeSpan.FromSeconds(2));
//    //var ConnectTask = Task.Factory.FromAsync(client.BeginConnect, client.EndConnect, remoteEP, null, TaskCreationOptions.LongRunning);
//    var ConnectTask = Task.Factory.FromAsync(client.BeginConnect, client.EndConnect, remoteEP, null);
//    var completedTask = await Task.WhenAny(timeoutTask, ConnectTask)
//                                  .ConfigureAwait(false);
Satu
  • 25
  • 2
  • 8
  • Why are you using `Socket` instead of `TcpClient`, which has native TAP-based methods? – Daniel Mann Jun 10 '14 at 14:46
  • 1
    You need to close the socket to cancel a pending async socket operation: http://stackoverflow.com/a/5979692/1768303 – noseratio Jun 10 '14 at 22:38
  • @DanielMann: I don't know why, but the server doesn't accept my commands, when I try to send data as stream (TcpClient). I don't have access to the server, they are black boxes. – Satu Jun 11 '14 at 09:09
  • @Noseratio: Thank you for the link. If I want to use System.Threading.Timer on Windows.Forms the Interlocked methods make it complete thread safe? – Satu Jun 11 '14 at 09:13
  • @Satu, you could call `socket.Close` from any thread. That said, if you do `await `ReceiveTaskAsync` on a UI thread, the continuation after socket termination will happen on the UI thread. – noseratio Jun 12 '14 at 01:42

0 Answers0