首页 > 解决方案 > IAsyncDisposable 参考实现错误?

问题描述

Microsoft 为需要同时实现 IDisposable 和 IAsyncDisposable 的类提供了一个引用实现,比如说因为它们同时具有这两者的成员。

https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync

我在下面包含了完整的实现。这些行Dispose(disposing)是我不明白的部分。

(_asyncDisposableResource as IDisposable)?.Dispose();
...
_asyncDisposableResource = null;

似乎如果我有一个实例CustomDisposableDispose()在此之前被调用,DisposeAsync()那么该_asyncDispoableResource字段将Dispose()调用它而不是DisposeAsync(如果它有一个),然后无条件地设置为 null。在这种情况下,似乎_asyncDispoableResource永远不会正确处理,即使稍后DisposeAsync()在实例上调用也是如此。CustomDisposable

完整参考代码:

using System;
using System.IO;
using System.Threading.Tasks;

namespace Samples
{
    public class CustomDisposable : IDisposable, IAsyncDisposable
    {
        IDisposable _disposableResource = new MemoryStream();
        IAsyncDisposable _asyncDisposableResource = new MemoryStream();

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

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

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

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _disposableResource?.Dispose();
                (_asyncDisposableResource as IDisposable)?.Dispose();
            }

            _disposableResource = null;
            _asyncDisposableResource = null;
        }

        protected virtual async ValueTask DisposeAsyncCore()
        {
            if (_asyncDisposableResource is not null)
            {
                await _asyncDisposableResource.DisposeAsync().ConfigureAwait(false);
            }

            if (_disposableResource is IAsyncDisposable disposable)
            {
                await disposable.DisposeAsync().ConfigureAwait(false);
            }
            else
            {
                _disposableResource.Dispose();
            }

            _asyncDisposableResource = null;
            _disposableResource = null;
        }
    }
}

标签: c#async-awaitdisposeidisposable

解决方案


引用您的参考资料:

在实现 IAsyncDisposable 接口时,通常类也将实现 IDisposable 接口。IAsyncDisposable 接口的一个好的实现模式是为同步或异步处置做好准备。

这意味着通过 "classic" 处理一个对象就足够了,从不调用Dispose它应该没关系。DisposeAsync这就是资源设置为 的原因null,因此很明显它已经被异步处理了。一次性参考的实际实现必须为此做好准备。


推荐阅读