处理泄漏的IAsyncDisposable实例的推荐方法是什么? [英] What's the recommended way to deal with leaked IAsyncDisposable instances?

查看:59
本文介绍了处理泄漏的IAsyncDisposable实例的推荐方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经熟悉了C#8& C中添加的(计划中的)某些内容..NET Core 3.0,并且不确定实现 IAsyncDisposable (在撰写本文时,此链接实际上没有指导).

I've been familiarizing myself with some of the things (that are planned to be) added in C# 8 & .NET Core 3.0, and am unsure on the correct way to implement IAsyncDisposable (at time of writing, this link has literally no guidance).

特别是,我不清楚在未明确处理实例的情况下该怎么办-也就是说,它没有使用(...)包裹在 async中和 .DisposeAsync()未被明确调用.

In particular, it is unclear to me what to do in the case when an instance isn't explicitly disposed - that is, it isn't wrapped in an async using(...) and .DisposeAsync() isn't explicitly called.

我的第一个想法是要做与实现

My first thought was to do that same thing I'd do when implementing IDisposable:

  • 我的 DisposeAsync()实现使用 dispose:true
  • 调用 DisposeAsync(bool dispose)
  • 实现一个终结器(使用〜MyType()),该终结器将调用 DisposeAsync(dispose:false)
  • DisposeAsync(bool处置)实际上释放和/或处置所有内容,并在 dispose == true 时禁止最终确定.
  • My DisposeAsync() implementation calls a DisposeAsync(bool disposing) with disposing: true
  • Implement a finalizer (with ~MyType()) that calls DisposeAsync(disposing: false)
  • DisposeAsync(bool disposing) actually frees and/or disposes everything, and suppresses finalizing if disposing == true.

我担心的是,终结器中没有什么要等待 DisposeAsync(bool)的结果的,而显式地等待终结器似乎真的很危险.

My concerns are that there's nothing to await the results of DisposeAsync(bool) in the finalizer, and explicitly waiting in a finalizer seems really really dangerous.

当然,只是泄漏"似乎也不理想.

Of course "just leak" also seems less than ideal.

为具体起见,下面是一个(简化的)示例类,其中 具有终结器:

To make this concrete, here's a (simplified) example class that does have a finalizer:

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 实例有什么指导吗?

So, is there any guidance around proper handling of leaked IAsyncDisposable instances?

推荐答案

基于在.NET Core类中如何实现的示例(例如

Basing on examples of how it's implemented inside .NET Core classes (like here) and some recommendations from there, I'd say that when you need to implement IAsyncDisposable, the good practice would be to implement both IAsyncDisposable and IDisposable. In this case IAsyncDisposable will be only responsible for explicit scenarios when asyncronus disposal is needed, while IDisposable is supposed to be implemented as usual according to disposable pattern practices and it's going to serve all fallback scenarios including those when things come to finalization. Thus you don't need to have anything like DisposeAsync(bool disposing) - the asynchronous disposal cannot and shouldn't happen in a finalizer. The only bad news that you'll have to support both paths for resources reclaiming (synchronous and asynchronous).

这篇关于处理泄漏的IAsyncDisposable实例的推荐方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆