spread dispose pattern

This commit is contained in:
JanEggers
2019-12-21 09:09:03 +01:00
parent 698f0b66d2
commit a77e0b8dde
5 changed files with 64 additions and 53 deletions
@@ -16,7 +16,7 @@ using MQTTnet.Server;
namespace MQTTnet.Extensions.ManagedClient namespace MQTTnet.Extensions.ManagedClient
{ {
public class ManagedMqttClient : IManagedMqttClient public class ManagedMqttClient : Disposable, IManagedMqttClient
{ {
private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>(); private readonly BlockingQueue<ManagedMqttApplicationMessage> _messageQueue = new BlockingQueue<ManagedMqttApplicationMessage>();
@@ -42,15 +42,15 @@ namespace MQTTnet.Extensions.ManagedClient
private Task _maintainConnectionTask; private Task _maintainConnectionTask;
private ManagedMqttClientStorageManager _storageManager; private ManagedMqttClientStorageManager _storageManager;
private bool _disposed;
public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger) public ManagedMqttClient(IMqttClient mqttClient, IMqttNetChildLogger logger)
{ {
_mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient)); _mqttClient = mqttClient ?? throw new ArgumentNullException(nameof(mqttClient));
if (logger == null) throw new ArgumentNullException(nameof(logger)); if (logger == null) throw new ArgumentNullException(nameof(logger));
_logger = logger.CreateChildLogger(nameof(ManagedMqttClient)); _logger = logger.CreateChildLogger(nameof(ManagedMqttClient));
Options = new ManagedMqttClientOptions();
} }
public bool IsConnected => _mqttClient.IsConnected; public bool IsConnected => _mqttClient.IsConnected;
@@ -242,36 +242,25 @@ namespace MQTTnet.Extensions.ManagedClient
return Task.FromResult(0); return Task.FromResult(0);
} }
public void Dispose() protected override void Dispose(bool disposing)
{ {
if (_disposed) if (disposing)
{ {
return; StopPublishing();
} StopMaintainingConnection();
_disposed = true; if (_maintainConnectionTask != null)
{
StopPublishing(); _maintainConnectionTask.GetAwaiter().GetResult();
StopMaintainingConnection(); _maintainConnectionTask = null;
}
if (_maintainConnectionTask != null)
{ _messageQueue.Dispose();
Task.WaitAny(_maintainConnectionTask); _messageQueueLock.Dispose();
_maintainConnectionTask = null; _mqttClient.Dispose();
} _subscriptionsQueuedSignal.Dispose();
_messageQueue.Dispose();
_messageQueueLock.Dispose();
_mqttClient.Dispose();
_subscriptionsQueuedSignal.Dispose();
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(ManagedMqttClient));
} }
base.Dispose(disposing);
} }
private async Task MaintainConnectionAsync(CancellationToken cancellationToken) private async Task MaintainConnectionAsync(CancellationToken cancellationToken)
@@ -292,7 +281,7 @@ namespace MQTTnet.Extensions.ManagedClient
} }
finally finally
{ {
if (!_disposed) if (!IsDisposed)
{ {
try try
{ {
@@ -10,10 +10,11 @@ using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using MQTTnet.Channel; using MQTTnet.Channel;
using MQTTnet.Client.Options; using MQTTnet.Client.Options;
using MQTTnet.Internal;
namespace MQTTnet.Implementations namespace MQTTnet.Implementations
{ {
public class MqttTcpChannel : IMqttChannel public class MqttTcpChannel : Disposable, IMqttChannel
{ {
private readonly IMqttClientOptions _clientOptions; private readonly IMqttClientOptions _clientOptions;
private readonly MqttClientTcpOptions _options; private readonly MqttClientTcpOptions _options;
@@ -94,7 +95,7 @@ namespace MQTTnet.Implementations
public Task DisconnectAsync(CancellationToken cancellationToken) public Task DisconnectAsync(CancellationToken cancellationToken)
{ {
Dispose(); Cleanup();
return Task.FromResult(0); return Task.FromResult(0);
} }
@@ -158,7 +159,7 @@ namespace MQTTnet.Implementations
} }
} }
public void Dispose() private void Cleanup()
{ {
// When the stream is disposed it will also close the socket and this will also dispose it. // When the stream is disposed it will also close the socket and this will also dispose it.
// So there is no need to dispose the socket again. // So there is no need to dispose the socket again.
@@ -177,6 +178,15 @@ namespace MQTTnet.Implementations
_stream = null; _stream = null;
} }
protected override void Dispose(bool disposing)
{
if (disposing)
{
Cleanup();
}
base.Dispose(disposing);
}
private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ {
if (_options.TlsOptions.CertificateValidationCallback != null) if (_options.TlsOptions.CertificateValidationCallback != null)
@@ -112,7 +112,7 @@ namespace MQTTnet.Implementations
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false); await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
} }
Dispose(); Cleanup();
} }
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
@@ -146,24 +146,29 @@ namespace MQTTnet.Implementations
{ {
if (disposing) if (disposing)
{ {
_sendLock?.Dispose(); Cleanup();
_sendLock = null;
try
{
_webSocket?.Dispose();
}
catch (ObjectDisposedException)
{
}
finally
{
_webSocket = null;
}
} }
base.Dispose(disposing); base.Dispose(disposing);
} }
private void Cleanup()
{
_sendLock?.Dispose();
_sendLock = null;
try
{
_webSocket?.Dispose();
}
catch (ObjectDisposedException)
{
}
finally
{
_webSocket = null;
}
}
private IWebProxy CreateProxy() private IWebProxy CreateProxy()
{ {
if (string.IsNullOrEmpty(_options.ProxyOptions?.Address)) if (string.IsNullOrEmpty(_options.ProxyOptions?.Address))
+2
View File
@@ -4,6 +4,8 @@ namespace MQTTnet.Internal
{ {
public class Disposable : IDisposable public class Disposable : IDisposable
{ {
protected bool IsDisposed => _isDisposed;
protected void ThrowIfDisposed() protected void ThrowIfDisposed()
{ {
if (_isDisposed) if (_isDisposed)
@@ -2,11 +2,12 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MQTTnet.Exceptions; using MQTTnet.Exceptions;
using MQTTnet.Internal;
using MQTTnet.Packets; using MQTTnet.Packets;
namespace MQTTnet.PacketDispatcher namespace MQTTnet.PacketDispatcher
{ {
public sealed class MqttPacketAwaiter<TPacket> : IMqttPacketAwaiter where TPacket : MqttBasePacket public sealed class MqttPacketAwaiter<TPacket> : Disposable, IMqttPacketAwaiter where TPacket : MqttBasePacket
{ {
private readonly TaskCompletionSource<MqttBasePacket> _taskCompletionSource = new TaskCompletionSource<MqttBasePacket>(); private readonly TaskCompletionSource<MqttBasePacket> _taskCompletionSource = new TaskCompletionSource<MqttBasePacket>();
private readonly ushort? _packetIdentifier; private readonly ushort? _packetIdentifier;
@@ -52,9 +53,13 @@ namespace MQTTnet.PacketDispatcher
Task.Run(() => _taskCompletionSource.TrySetCanceled()); Task.Run(() => _taskCompletionSource.TrySetCanceled());
} }
public void Dispose() protected override void Dispose(bool disposing)
{ {
_owningPacketDispatcher.RemovePacketAwaiter<TPacket>(_packetIdentifier); if (disposing)
{
_owningPacketDispatcher.RemovePacketAwaiter<TPacket>(_packetIdentifier);
}
base.Dispose(disposing);
} }
} }
} }