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