MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Does IAsyncDisposable Have a Reference Implementation?"
Answer 58483961
Update: .NET Documentation now has an article Implement a DisposeAsync method that describes recommended IAsyncDisposable implementation for non-sealed class that needs to support both synchronous and asynchronous disposal. It recommends adding separate virtual DisposeAsyncCore method:
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; } }
The example assumes that only indirectly owned unmanaged resources can be disposed asynchronously. Directly owned managed resources are always disposed synchronously in
protected virtual void Dispose
method.
Old answer: The DisposeAsync method, unlike regular
Dispose
, should not be called from finalizer. Finalizers already run in dedicated thread and don't block anything, so there's no need. Therefore,DisposeAsync
can always dispose both unmanaged and managed resources, and you don't need to implement a separateDisposeAsync(bool disposing)
method.The example of
IAsyncDisposable
implementation can be found in the sources of the new .NET Core type, Utf8JsonWriter (it is a sealed class and therefore don't use virtual method):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; }
Basically, it should do the same things as
Dispose(true)
in regular Disposable pattern, but asynchronously, if possible. If it's not possible to do disposal asynchronously, but you still need to implement this interface for some reason, you can fall back to synchronous disposal and return completed ValueTask after that, as done in System.IO.Stream.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.