diff --git a/Source/MQTTnet/Client/MqttClient.cs b/Source/MQTTnet/Client/MqttClient.cs index 0a408d08..05330b5d 100644 --- a/Source/MQTTnet/Client/MqttClient.cs +++ b/Source/MQTTnet/Client/MqttClient.cs @@ -29,7 +29,7 @@ namespace MQTTnet.Client internal Task _keepAliveMessageSenderTask; private IMqttChannelAdapter _adapter; private bool _cleanDisconnectInitiated; - private TaskCompletionSource _disconnectReason; + private int _disconnectGate; public MqttClient(IMqttClientAdapterFactory channelFactory, IMqttNetLogger logger) { @@ -59,7 +59,7 @@ namespace MQTTnet.Client _packetDispatcher.Reset(); _cancellationTokenSource = new CancellationTokenSource(); - _disconnectReason = new TaskCompletionSource(); + _disconnectGate = 0; _adapter = _adapterFactory.CreateClientAdapter(options, _logger); _logger.Verbose($"Trying to connect with server ({_options.ChannelOptions})."); @@ -88,7 +88,7 @@ namespace MQTTnet.Client { _logger.Error(exception, "Error while connecting with server."); - if (_disconnectReason.TrySetException(exception)) + if (!DisconnectIsPending()) { await DisconnectInternalAsync(null, exception).ConfigureAwait(false); } @@ -110,7 +110,7 @@ namespace MQTTnet.Client } finally { - if (_disconnectReason.TrySetCanceled()) + if (!DisconnectIsPending()) { await DisconnectInternalAsync(null, null).ConfigureAwait(false); } @@ -361,7 +361,7 @@ namespace MQTTnet.Client _logger.Error(exception, "Unhandled exception while sending/receiving keep alive packets."); } - if (_disconnectReason.TrySetException(exception)) + if (!DisconnectIsPending()) { await DisconnectInternalAsync(_keepAliveMessageSenderTask, exception).ConfigureAwait(false); } @@ -410,7 +410,7 @@ namespace MQTTnet.Client _packetDispatcher.Dispatch(exception); - if (_disconnectReason.TrySetException(exception)) + if (!DisconnectIsPending()) { await DisconnectInternalAsync(_packetReceiverTask, exception).ConfigureAwait(false); } @@ -545,5 +545,10 @@ namespace MQTTnet.Client { } } + + private bool DisconnectIsPending() + { + return Interlocked.CompareExchange(ref _disconnectGate, 1, 0) != 0; + } } } \ No newline at end of file diff --git a/Tests/MQTTnet.Core.Tests/MqttServerTests.cs b/Tests/MQTTnet.Core.Tests/MqttServerTests.cs index e4e5b3b9..0404ccc0 100644 --- a/Tests/MQTTnet.Core.Tests/MqttServerTests.cs +++ b/Tests/MQTTnet.Core.Tests/MqttServerTests.cs @@ -669,25 +669,24 @@ namespace MQTTnet.Core.Tests MqttQualityOfServiceLevel filterQualityOfServiceLevel, int expectedReceivedMessagesCount) { - var serverAdapter = new TestMqttServerAdapter(); - var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger()); + var s = new MqttFactory().CreateMqttServer(); var receivedMessagesCount = 0; try { await s.StartAsync(new MqttServerOptions()); - var c1 = await serverAdapter.ConnectTestClient("c1"); - var c2 = await serverAdapter.ConnectTestClient("c2"); - + var c1 = new MqttFactory().CreateMqttClient(); c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++; - + await c1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build()); await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build()); + + var c2 = new MqttFactory().CreateMqttClient(); + await c2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build()); await c2.PublishAsync(builder => builder.WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel)); await Task.Delay(500); await c1.UnsubscribeAsync(topicFilter); - await Task.Delay(500); } finally