/// <inheritdoc /> public void Connect(ClientConnectionConfiguration configuration) { _configuration = configuration; try { // wait for semaphore to be release by SendAsync // otherwise creating new client while SendAsync is using the old client would cause weired behavior _semaphore.Wait(); // connect the tcp client var endPoint = configuration.EndPoint ?? throw new ArgumentNullException(nameof(configuration.EndPoint)); // dispose the old socket and client Socket?.Dispose(); Client?.Dispose(); // create new tcp socket var newTcpSocket = TcpSocket.NewFromEndPoint(endPoint); // once the TcpSocket is connected, create new client from it var newClient = _serviceProvider.GetRequiredService <IClient>(); newClient.Setup(newTcpSocket); newClient.OnDataReceived += ClientDataReceived; newClient.OnDisconnected += ClientDisconnected; // start receiving data from server newClient.StartReceiveProcess(); Client = newClient; Socket = newTcpSocket; _logger.LogInformation( $"Broker client connected to: {_configuration.EndPoint} with auto connect: {_configuration.AutoReconnect}"); } catch (Exception e) { // if auto reconnect is active, try to reconnect if (_configuration.AutoReconnect) { _logger.LogWarning( $"Couldn't connect to endpoint: {_configuration.EndPoint} with error: {e} retrying in 1 second"); Thread.Sleep(1000); Reconnect(); } else { throw; } } finally { _semaphore.Release(); } // note: must be called after releasing semaphore OnConnected?.Invoke(this, new ClientConnectionEventArgs()); }