In a method of a module, I create a local URLConnection object, add handlers for some of its events, then call its async Send method.
dim Downloader as new URLConnection
AddHandler Downloader.error, AddressOf DownloadError
AddHandler Downloader.FileReceived, AddressOf DownloadFileReceived
Downloader.Send("GET",URL, DownLoadFile,15)
When is the URLConnection object destroyed and the handlers removed? After Send terminates in some event?
Do I need to be concerned about handler removal? WeakAddressOf can’t be used, and handlers are added to a new URLConnection instance every time the method is called.
If the DownloadError and DownloadFileReceived methods are also module methods then the URLConnection is destroyed when the Downloader local variable goes out of scope.
It’s when the handler method belongs to another object that you have to be concerned about creating zombies with AddHandler.
When the “Downloader” object goes out of scope, its handlers, if any, should be auto detached by the super destructor of the URLConnection Class (not user’s) and everything should be auto released after.
Yes, those methods are in the same module. The call to Send is the last statement in the method in which Downloader is instantiated, so technically it goes “out of scope”, as that method terminates and execution returns to the main event loop, but the Downloader object still exists somewhere, running asynchronously. I guess it self-destructs after calling one of its terminating events like FileReceived or Error, right?
Maybe there’s a instance manager for this kind of class that keeps them around while there’s an active connection. The other option would be just the object super destructor just drop the connection before continuing its release, or just there’s a bug and it’s not being released in some cases. Someone at Xojo should explain the internals as the docs are obscure.
Any time you use AddHandler, you must have a corresponding RemoveHandler call. Keep in mind that you cannot use the Destructor for this because the destructor will not fire if an AddHandler is in place.
If you only need to call run once, you can certainly call RemoveHandler from within the method that was called, using the object that was passed. If not, I suggest that you make a method designed for cleaning up.
If you want more control, use a Delegate and a property that uses that delegate type. Then it’s as simple as setting the property to nil.
Where would I do this in my application? In the delegate methods themselves, i.e. the event handlers for URLConnection.Error and URLConnection.FileReceived?
No other place in the code can possibly know what the status of the URL connection object is, as the method that instantiated it has terminated and the object is technically “out of scope”, as previously discussed.
Now this gets a bit hazy. Do you mean that instead of doing AddHandler AddressOf, and then later doing RemoveHandler AddressOf, I can store the address of the method in a delegate and use the delegate in the add/remove handler statements? That seems to work, but I can’t see where setting it to Nil comes in.
RemoveHandler requires as an argument the name of the event, e.g. “MyTimer.Action”, but in my case the object whose event is being handled cannot be referenced because it’s out of scope - I couldn’t create a RemoveHandler statement that would compile.
I guess the simple solution is to make the URLConnection a module property rather than instantiating it in a method so it can be referenced at any time, but that’s a little OT from my original question. Maybe the answer to my original question is “Don’t do that”, but it seems nice and elegant apart from the pesky handlers that I was hoping would go away by themselves.
The implication of what you say is that there’s another way of assigning a method as handler for an event, in this case a delegate method. Is this so?