Reputation: 5717
Is there any way I can get the status of a TcpClient async connection? Using the following code, how can I get the status of the client using the Connected property? I try to establish a remote connection asynchronously but in the same time don't wait more then 5 seconds ...
TcpClient client = new TcpClient();
Task tsk = Task.Factory.StartNew(() =>
{
client.ConnectAsync(host, port);
// client.Connect (this is always false)
});
tsk.Wait(5000);
// client.Connect (or if I use it here, this is always false)
Upvotes: 3
Views: 15334
Reputation: 131374
.Result
and .Wait(...)
are blocking, not asynchronous. The asynchronous way to connect with a timeout is to use a CancellationToken created by a CancellationTokenSource set to trigger after that timeout :
var cts=new CancellationTokenSource(TimeSpan.FromSeconds(5));
...
await client.ConnectAsync(host,port,cts.Token);
Upvotes: 2
Reputation: 2760
No, @Jon is wrong! The IsCompleted
will just tell you if the task has been completed, it doesn't not indicate that the connection has been made. For example, if no server is open on the specific address/port, IsCompleted
will return true
anyway... You should check IsFaulted
instead.
Here is code, that I have put together from pieces of the internet and I have actually tested:
string address = "127.0.0.1";
int port = 8888;
int connectTimeoutMilliseconds = 1000;
var tcpClient = new TcpClient();
var connectionTask = tcpClient
.ConnectAsync(address, port).ContinueWith(task => {
return task.IsFaulted ? null : tcpClient;
}, TaskContinuationOptions.ExecuteSynchronously);
var timeoutTask = Task.Delay(connectTimeoutMilliseconds)
.ContinueWith<TcpClient>(task => null, TaskContinuationOptions.ExecuteSynchronously);
var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();
var resultTcpClient = resultTask.GetAwaiter().GetResult();
// Or by using `await`:
// var resultTcpClient = await resultTask.ConfigureAwait(false);
if (resultTcpClient != null)
{
// Connected!
}
else
{
// Not connected
}
Upvotes: 15
Reputation: 437376
First off, do not create a new Task
of your own; this is a bug. ConnectAsync
already returns a Task
that represents the connection attempt:
var tsk = client.ConnectAsync(host, port);
tsk.Wait(5000);
After the wait returns, check the IsCompleted
property of the task; it will be true
if and only if the connection was established.
Upvotes: 10