Imagine having a class that does some stuff and displays the results in modal window. The class has a costly dispose, i.e. it has to free resources which may take some seconds. The problem: When I close the window, I call the dispose method to free all the objects. This results in the window freezing for some seconds before closing. I want to avoid that.
Research brought me to IAsyncDisposable. My working implementation looks like this:
public class MyClass : IAsyncDisposable, IDisposable
{
private bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// Disposing some costly stuff
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public async ValueTask DisposeAsync()
{
await Task.Run(Dispose);
}
}
Calling it via:
myClassInstance.DisposeAsync().ConfigureAwait(false);
Question: Is this valid, especially the implementation of the DisposeAsync method? Can something go wrong here? It works nicely, but I am somehow not convinced.
I did some research on this but did not find anybody that did it this way. Even more, Visual Studio tells me that I should do something with the ValueTask I get from calling the DisposeAsync method. Any comments on that?
If you want to dispose something in the background (and that disposal is inherently synchronous), just dispose it in the background; for example instead of:
obj.Dispose();
consider:
ThreadPool.QueueUserWorkItem<IDisposable>(static s => s.Dispose(), obj, false);
Ultimately asynchronous and concurrent are related but different concepts; in this case what we want is concurrency, and async is unrelated - no need (or purpose) to add or remove it.