My question is when performing actions such as connecting to and receiving data from TCP sockets is Τask.Υield
a suitable way to ensure these happen while allowing the main thread to continue?
In my example I have an automation code that can be connecting to 200 devices via TCP, and sometimes they may be offline resulting in longer timeouts. I want the main thread that called the connect method to continue on with other tasks while all these sockets connect.
public async Task<bool> Connect()
{
await Task.Yield();
_disconnected = false;
_client = new TcpClient();
try
{
_client.Connect(_ipAddress, _port);
_failure = false;
_stream = _client.GetStream();
Connected?.Invoke(this, true);
var ReceivingThread = new Thread(Receive);
ReceivingThread.Start();
}
catch (Exception)
{
if (!_failure)
{
ErrorLog.Notice($"Failed to connect to {_ipAddress}");
}
_failure = true;
_ = Connect();
}
return (!_failure);
}
Ended up with this after comments from Fildor. Test fantastic for 10 hours with 100 clients retrying every 1 second.
public async Task<bool> Connect()
{
_client = new TcpClient();
_disconnected = false;
await Policy.Handle<Exception>(e => !_disconnected)
.WaitAndRetryForeverAsync(_ => (TimeSpan.FromSeconds(1)),
(exception, waitDuration) => {
if (!_failure)
{
ErrorLog.Notice($"Failed to connect to
{_ipAddress}");
}
_failure = true;
})
.ExecuteAndCaptureAsync(() =>
_client.ConnectAsync(_ipAddress, _port));
if(!_disconnected)
{
_failure = false;
_stream = _client.GetStream();
Connected?.Invoke(this, true);
Receive();
}
return !_failure;
}