Disposing Disposables
All disposable instances (i.e. that inherits from IDisposable, see Dispose Pattern for background) must be disposed after use, to ensure resources are released, connections are closed etc. In particular, SQL Database Access uses several types that must be disposed.
If you create an instance of a disposable type, you must ensure it is disposed; use the following guidelines:
If used across multiple method calls, or passed to another worker:
- DisposeOnFinished<TDisposable>(TDisposable), e.g. see the examples in Adb Keep Open Connection
- UsingActionWorker<TDisposable>, which also has an example
If created and disposed in a single method and thread, and without being passed to any other worker:
- A using statement, e.g. see the Custom Non-Adb Development example
- By explicitly calling Dispose() on the instance
Incorrect Disposal
As per the above guidelines, the following is a buggy implementation, since the execution order will be:
- Start the worker system action
- Start the
using
statement, which creates the disposable - Create the
ActionWorker
- Exit the
using
statement, and dispose the disposable - Run the
ActionWorker
, which will try to use the disposable (which has already been disposed)
await new WorkerSystem(nameof(UsingActionWorker_Disposes))
.Root(ws =>
{
// Note: Buggy implementation!
using (var disposable = new Disposable())
{
new ActionWorker(ws, "action", aw =>
{
// Use disposable...
});
}
}).StartAsync().ConfigureAwait(false);
A correct implementation would use
DisposeOnFinished<TDisposable>(TDisposable) or
UsingActionWorker<TDisposable> (instead of the using
statement) to ensure
correct disposal, or (much more rarely), await
the child worker(s) with an
RunChildrenAsync() overload before exiting the using
statement.