I have this object PreloadClient
which implements IDisposable
, I want to dispose it, but after the asynchronous methods finish their call... which
Why not disposing in the client_PreloadCompleted
method?
Similar to what thecoop offered, just with the Dispose
call inside the above method, after you have accessed all the needed data from inside the client object.
Edit: I think that is what orialmog offered as well.
If there are event handlers being registered, you can't really dispose the object while there are events that could be called on it. Your best bet is to make the containing class disposable & store the client in a class variable, to be disposed when the containing class is.
Something like
class ContainingClass : IDisposable
{
private PreloadClient m_Client;
private void Preload(SlideHandler slide)
{
m_Client = new PreloadClient())
m_Client.PreloadCompleted += client_PreloadCompleted;
m_Client.Preload(slide);
}
private void client_PreloadCompleted(object sender, SlidePreloadCompletedEventArgs e)
{
}
public void Dispose()
{
if (m_Client != null)
m_Client.Dispose();
}
}
Asynchronous waits and deterministic disposal don't mix very well. If you can find a way of splitting the code such that the disposable stuff goes in one class and the events go in another, that would make everything simpler.
Why not dispose the client in the callback?
You shouldn't use the using
construct, but rather dispose your objects when they are no longer needed:
// keep a list of strong references to avoid garbage collection,
// and dispose them all in case we're disposing the encapsulating object
private readonly List<PreloadClient> _activeClients = new List<PreloadClient>();
private void Preload(SlideHandler slide)
{
PreloadClient client = new PreloadClient();
_activeClients.Add(client);
client.PreloadCompleted += client_PreloadCompleted;
client.Preload(slide);
}
private void client_PreloadCompleted(object sender,
SlidePreloadCompletedEventArgs e)
{
PreloadClient client = sender as PreloadClient;
// do stuff
client.PreloadCompleted -= client_PreloadCompleted;
client.Dispose();
_activeClients.Remove(client);
}
in this case, you have to dispose all clients when disposing the main class:
protected override Dispose(bool disposing)
{
foreach (PreloadClient client in _activeClients)
{
client.PreloadCompleted -= client_PreloadCompleted;
client.Dispose();
}
_activeClients.Clear();
base.Dispose(disposing);
}
Note that this implementation is not thread safe
_activeClients
list must be made thread-safe, as your PreloadCompleted
method is called from a different threadtry
/finally
block inside your event handler, to make sure that the object gets disposed in all casesI have a few ideas: