Task DisconnectInternalAsync(Task sender, Exception exception, MqttClientConnectResult connectResult) { var clientWasConnected = IsConnected; if (!DisconnectIsPendingOrFinished()) { return(DisconnectCoreAsync(sender, exception, connectResult, clientWasConnected)); } return(PlatformAbstractionLayer.CompletedTask); }
async Task DisconnectCoreAsync(Task sender, Exception exception, MqttClientConnectResult connectResult, bool clientWasConnected) { TryInitiateDisconnect(); try { if (_adapter != null) { _logger.Verbose("Disconnecting [Timeout={0}]", Options.CommunicationTimeout); await _adapter.DisconnectAsync(Options.CommunicationTimeout, CancellationToken.None).ConfigureAwait(false); } _logger.Verbose("Disconnected from adapter."); } catch (Exception adapterException) { _logger.Warning(adapterException, "Error while disconnecting from adapter."); } try { var receiverTask = WaitForTaskAsync(_packetReceiverTask, sender); var publishPacketReceiverTask = WaitForTaskAsync(_publishPacketReceiverTask, sender); var keepAliveTask = WaitForTaskAsync(_keepAlivePacketsSenderTask, sender); await Task.WhenAll(receiverTask, publishPacketReceiverTask, keepAliveTask).ConfigureAwait(false); } catch (Exception innerException) { _logger.Warning(innerException, "Error while waiting for internal tasks."); } finally { Cleanup(); _cleanDisconnectInitiated = false; CompareExchangeConnectionStatus(MqttClientConnectionStatus.Disconnected, MqttClientConnectionStatus.Disconnecting); _logger.Info("Disconnected."); var disconnectedHandler = DisconnectedHandler; if (disconnectedHandler != null) { // This handler must be executed in a new thread because otherwise a dead lock may happen // when trying to reconnect in that handler etc. Task.Run(() => disconnectedHandler.HandleDisconnectedAsync(new MqttClientDisconnectedEventArgs(clientWasConnected, exception, connectResult, _disconnectReason))).RunInBackground(_logger); } } }
public MqttClientConnectedEventArgs(MqttClientConnectResult connectResult) { ConnectResult = connectResult ?? throw new ArgumentNullException(nameof(connectResult)); }
public async Task <MqttClientConnectResult> ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (options.ChannelOptions == null) { throw new ArgumentException("ChannelOptions are not set."); } ThrowIfConnected("It is not allowed to connect with a server after the connection is established."); ThrowIfDisposed(); if (CompareExchangeConnectionStatus(MqttClientConnectionStatus.Connecting, MqttClientConnectionStatus.Disconnected) != MqttClientConnectionStatus.Disconnected) { throw new InvalidOperationException("Not allowed to connect while connect/disconnect is pending."); } MqttClientConnectResult connectResult = null; try { Options = options; _packetIdentifierProvider.Reset(); _packetDispatcher.CancelAll(); _backgroundCancellationTokenSource = new CancellationTokenSource(); var backgroundCancellationToken = _backgroundCancellationTokenSource.Token; var adapter = _adapterFactory.CreateClientAdapter(options); _adapter = adapter; using (var combined = CancellationTokenSource.CreateLinkedTokenSource(backgroundCancellationToken, cancellationToken)) { _logger.Verbose("Trying to connect with server '{0}' (Timeout={1}).", options.ChannelOptions, options.CommunicationTimeout); await adapter.ConnectAsync(options.CommunicationTimeout, combined.Token).ConfigureAwait(false); _logger.Verbose("Connection with server established."); _publishPacketReceiverQueue = new AsyncQueue <MqttPublishPacket>(); _publishPacketReceiverTask = Task.Run(() => ProcessReceivedPublishPackets(backgroundCancellationToken), backgroundCancellationToken); _packetReceiverTask = Task.Run(() => TryReceivePacketsAsync(backgroundCancellationToken), backgroundCancellationToken); connectResult = await AuthenticateAsync(adapter, options.WillMessage, combined.Token).ConfigureAwait(false); } _lastPacketSentTimestamp = DateTime.UtcNow; if (Options.KeepAlivePeriod != TimeSpan.Zero) { _keepAlivePacketsSenderTask = Task.Run(() => TrySendKeepAliveMessagesAsync(backgroundCancellationToken), backgroundCancellationToken); } CompareExchangeConnectionStatus(MqttClientConnectionStatus.Connected, MqttClientConnectionStatus.Connecting); _logger.Info("Connected."); var connectedHandler = ConnectedHandler; if (connectedHandler != null) { await connectedHandler.HandleConnectedAsync(new MqttClientConnectedEventArgs(connectResult)).ConfigureAwait(false); } return(connectResult); } catch (Exception exception) { _disconnectReason = MqttClientDisconnectReason.UnspecifiedError; _logger.Error(exception, "Error while connecting with server."); await DisconnectInternalAsync(null, exception, connectResult).ConfigureAwait(false); throw; } }