处理泄漏的 IAsyncDisposable 实例的推荐方法是什么?

What's the recommended way to deal with leaked IAsyncDisposable instances?

我一直在熟悉 C# 8 和 .NET Core 3.0 中添加的一些(计划中的)内容,但不确定实现 IAsyncDisposable 的正确方法(当时写作,这个 link 几乎没有任何指导)。

特别是,我不清楚在未明确处置实例的情况下该怎么办 - 也就是说,它未包装在 async using(...) 中且 .DisposeAsync() 未包装'明确调用。

我的第一个想法是做与实施 IDisposable:

时相同的事情

我担心的是在终结器中没有等待 DisposeAsync(bool) 的结果,并且在终结器中显式等待似乎真的很危险。

当然"just leak"也似乎不太理想。

为了具体说明,这里有一个(简化的)示例 class 确实 有一个终结器:

internal sealed class TestAsyncReader: IAsyncDisposable
{
    private bool IsDisposed => Inner == null;
    private TextReader Inner;
    internal TestAsyncReader(TextReader inner)
    {
        Inner = inner;
    }

    // the question is, should this exist?
    ~TestAsyncReader()
    {
        DisposeAsync(disposing: false);
    }

    private ValueTask DisposeAsync(bool disposing)
    {
        // double dispose is legal, but try and do nothing anyway
        if (IsDisposed)
        {
            return default;
        }

        // should a finalizer even exist?
        if (disposing)
        {
            GC.SuppressFinalize(this);
        }

        // in real code some resources explicitly implement IAsyncDisposable,
        //   but for illustration purposes this code has an interface test
        if (Inner is IAsyncDisposable supportsAsync)
        {
            var ret = supportsAsync.DisposeAsync();
            Inner = null;
            return ret;
        }

        // dispose synchronously, which is uninteresting
        Inner.Dispose();
        Inner = null;
        return default;
    }

    public ValueTask DisposeAsync()
    => DisposeAsync(disposing: true);
}

那么,是否有任何关于正确处理泄漏的 IAsyncDisposable 实例的指南?

基于如何在 .NET Core 中实现它的示例 类(如 here) and some recommendations from there,我会说当您需要实现 IAsyncDisposable 时,好的做法是实现 IAsyncDisposableIDisposable。在这种情况下,IAsyncDisposable 将只负责需要异步处理时的显式场景,而 IDisposable 应该像往常一样实现到一次性模式实践,它将服务于所有回退场景,包括那些当事情完成时的场景。因此你不需要像 DisposeAsync(bool disposing) 这样的东西 - 异步处理不能也不应该在终结器中发生。唯一的坏消息是您必须支持两种资源回收路径(同步和异步)。