Я ознакомился с некоторыми вещами (которые планируется сделать), добавленными в C # 8 и .NET Core 3.0, и не уверен в правильном способе реализации IAsyncDisposable (в то время написания, эта ссылка буквально не имеет никаких указаний).
В частности, мне неясно, что делать в случае, когда экземпляр явно не расположен, то есть он не заключен в async using(...)
и .DisposeAsync()
явно не вызывается.
Моей первой мыслью было сделать то же самое, что я делал бы при реализации IDisposable :
- Моя
DisposeAsync()
реализация вызывает DisposeAsync(bool disposing)
с disposing: true
- Реализация финализатора (с
~MyType()
), который вызывает DisposeAsync(disposing: false)
DisposeAsync(bool disposing)
фактически освобождает и / или удаляет все и подавляет завершение, если disposing == true
.
Меня беспокоит, что нечего ждать результатов DisposeAsync(bool)
в финализаторе, и явное ожидание в финализаторе кажется действительно очень опасным.
Конечно, "просто утечка" тоже кажется не идеальной.
Чтобы сделать этот конкретный пример, вот (упрощенный) пример класса, в котором имеет финализатор:
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
экземпляров?