From 70c855c301636e27d33570d3a4318e9b37825469 Mon Sep 17 00:00:00 2001 From: TyKonKet Date: Sat, 10 Jan 2026 15:05:41 +0100 Subject: [PATCH] Improve TCP connect timeout handling in ModbusTcpClient Ensure exceptions from ConnectAsync are observed to prevent unhandled task exceptions. Close TcpClient on timeout to cancel pending connections and enhance robustness against connection failures. --- src/FluentModbus/Client/ModbusTcpClient.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/FluentModbus/Client/ModbusTcpClient.cs b/src/FluentModbus/Client/ModbusTcpClient.cs index e1cd49c..6a15905 100755 --- a/src/FluentModbus/Client/ModbusTcpClient.cs +++ b/src/FluentModbus/Client/ModbusTcpClient.cs @@ -167,8 +167,19 @@ private void Initialize(TcpClient tcpClient, IPEndPoint? remoteEndpoint, ModbusE var isInternal = remoteEndpoint is not null; _tcpClient = (tcpClient, isInternal); - if (remoteEndpoint is not null && !tcpClient.ConnectAsync(remoteEndpoint.Address, remoteEndpoint.Port).Wait(ConnectTimeout)) - throw new Exception(ErrorMessage.ModbusClient_TcpConnectTimeout); + if (remoteEndpoint is not null) + { + var connectTask = tcpClient.ConnectAsync(remoteEndpoint.Address, remoteEndpoint.Port); + if (!connectTask.Wait(ConnectTimeout)) + { + // Ensure the task exception is observed to avoid triggering UnobservedTaskException handlers (which can crash the process or flood logs). + // Attaching a continuation that accesses task.Exception guarantees the exception is observed. + connectTask.ContinueWith(t => t.Exception, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously); + // Close the TcpClient to cancel the connection attempt. + tcpClient.Close(); + throw new Exception(ErrorMessage.ModbusClient_TcpConnectTimeout); + } + } // Why no method signature with NetworkStream only and then set the timeouts // in the Connect method like for the RTU client?