Как IDisposable и IAsyncDisposable работают вместе?

Класс ниже не sealed, что означает, что он считается наследственным. Я взял реализацию IDisposable/IAsyncDisposable отсюда и пытаюсь понять, почему .Disposeвызовы дублируются как в Dispose, так и в DisposeAsync. Сможет ли кто-нибудь объяснить мне, как это работает более глубоко / или я бы сказал, на низком уровне, чтобы я действительно знал, как его использовать в будущем?

      public class Client : IDisposable, IAsyncDisposable
{
    private readonly ILogger<Client> _logger;
    private readonly Channel<string> _outputChannel;
    private ClientWebSocket? _clientWebSocket;
    private CancellationTokenSource? _cancellationSource;
    private Task _receiving = Task.CompletedTask;
    private Task _sending = Task.CompletedTask;

    public Client(ILoggerFactory? loggerFactory = default)
    {
        _logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<Client>();
    }

    public bool IsDisposed { get; protected set; }

    ...

    /// <summary>
    ///     Checks if this object has been disposed.
    /// </summary>
    /// <exception cref="ObjectDisposedException">Thrown if the object has been disposed.</exception>
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    protected void DoDisposeChecks()
    {
        if (IsDisposed)
        {
            throw new ObjectDisposedException(nameof(Client));
        }
    }

    /// <summary>
    ///     Disposes of managed and unmanaged resources.
    /// </summary>
    /// <param name="disposeManaged">A value indicating whether or not to dispose of managed resources.</param>
    protected virtual void Dispose(bool disposeManaged)
    {
        if (IsDisposed)
        {
            return;
        }

        if (disposeManaged)
        {
            _logger.LogDebug("Socket {Id} is disposing", Id);

            _clientWebSocket?.Dispose();
            _cancellationSource?.Dispose();

            _outputChannel.Writer.TryComplete();

            _logger.LogDebug("Socket {Id} disposed", Id);
        }

        IsDisposed = true;
    }

    /// <summary>
    ///     Asynchronously disposes of managed resources.
    /// </summary>
    /// <returns>A task representing the asynchronous operation.</returns>
    protected virtual ValueTask DisposeAsyncCore()
    {
        if (IsDisposed)
        {
            return default;
        }

        _logger.LogDebug("Socket {Id} is disposing", Id);

        _clientWebSocket?.Dispose();
        _cancellationSource?.Dispose();

        _outputChannel.Writer.TryComplete();

        _logger.LogDebug("Socket {Id} disposed", Id);

        IsDisposed = true;

        return default;
    }

    /// <inheritdoc />
    public async ValueTask DisposeAsync()
    {
        await DisposeAsyncCore().ConfigureAwait(false);
        Dispose(false);
        GC.SuppressFinalize(this);
    }

    /// <inheritdoc />
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

0 ответов

Другие вопросы по тегам