IAsyncDisposable 有参考实现吗?

Muh*_*eed 5 .net c# idisposable .net-core

对于IDisposable,我经常使用抽象基类,因为实现它非常困难。主要是因为您可以使用该接口来处理托管和非托管引用,并且每个引用的处理方式都不同。

public abstract class Disposable : IDisposable
{
    ~Disposable() => this.Dispose(false);

    public bool IsDisposed { get; private set; }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void DisposeManaged() {}
    protected virtual void DisposeUnmanaged() {}

    protected void ThrowIfDisposed()
    {
        if (this.IsDisposed)
        {
            throw new ObjectDisposedException(this.GetType().Name);
        }
    }

    private void Dispose(bool disposing)
    {
        if (!this.IsDisposed)
        {
            if (disposing)
            {
                this.DisposeManaged();
            }

            this.DisposeUnmanaged();
            this.IsDisposed = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用IAsyncDisposable,我找不到参考实现。另外,我相信它只处理托管资源,主要是因为它太新了,并且没有需要异步处理的非托管资源。这样对吗?如果是这样,那么实现是微不足道的吗?

MSD*_*ght 5

更新: .NET 文档现在有一篇文章实现 DisposeAsync 方法,描述了需要支持同步和异步处置的非密封类的推荐 IAsyncDisposable 实现。它建议添加单独的虚拟 DisposeAsyncCore 方法:

using System;
using System.Text.Json;
using System.Threading.Tasks;

public class ExampleAsyncDisposable : IAsyncDisposable, IDisposable
{
    // To detect redundant calls
    private bool _disposed = false;

    // Created in .ctor, omitted for brevity.
    private Utf8JsonWriter _jsonWriter;

    public async ValueTask DisposeAsync()
    {
        await DisposeAsyncCore();

        Dispose(false);
        GC.SuppressFinalize(this);
    }

    protected virtual async ValueTask DisposeAsyncCore()
    {
        // Cascade async dispose calls
        if (_jsonWriter != null)
        {
            await _jsonWriter.DisposeAsync();
            _jsonWriter = null;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
        {
            return;
        }

        if (disposing)
        {
            _jsonWriter?.Dispose();
            // TODO: dispose managed state (managed objects).
        }

        // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
        // TODO: set large fields to null.

        _disposed = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

该示例假设只能异步处置间接拥有的非托管资源。直接拥有的托管资源始终在protected virtual void Dispose方法中同步处置。


旧答案:与常规方法不同,DisposeAsync 方法不应Dispose从终结器调用。终结器已经在专用线程中运行,并且不会阻止任何内容,因此没有必要。因此,DisposeAsync始终可以处置非托管和托管资源,并且不需要实现单独的DisposeAsync(bool disposing)方法。

实现示例可以在新的 .NET Core 类型Utf8JsonWriterIAsyncDisposable的源代码中找到(它是一个密封类,因此不使用虚方法):

public async ValueTask DisposeAsync()
{
    if (_stream == null)
    {
        // The conditions are ordered with stream first as that would be the most common mode
        if (_output == null)
        {
            return;
        }
    }

    await FlushAsync().ConfigureAwait(false);
    ResetHelper();

    _stream = null;
    _arrayBufferWriter = null;
    _output = null;
}
Run Code Online (Sandbox Code Playgroud)

基本上,它应该做与常规一次性模式相同的事情Dispose(true),但如果可能的话,是异步的。如果无法异步处理,但由于某种原因您仍然需要实现此接口,则可以回退到同步处理并返回已完成的 ValueTask,如System.IO.Stream中所做的那样。