WeakDelegate <> nil but method is gone

Not sure if this is new to 2013 or an existing bug, or just my misunderstanding…

I have a Class which creates a timer, adds a handler to that timer and when the timer fires, tries to Invoke a delegate for a method.

When I create the Delegate using WeakAddressOf, and then nil out the Class, I seem to be finding a situation where this code malfunctions:

  if me.callback <> nil and me.callback isa CallbackMethod then
    CallbackMethod(me.callback).invoke   // < --- getting a NilObjectException here!
  end if

Shouldn’t this be impossible? I thought the whole point of using WeakAddressOf was that if the Class it pointed to was destroyed, the delegate would also go to nil?

Hmm, seeing the same behavior in 2012, so this is probably not a 2013 / beta issue.

But I’m curious : Is there a way to detect that a Weak Delegate is invalid, aside from trying to invoke it and getting a NilObjectException?

See these posts:

we run into this problem today, too. So I filled feature request.

see
https://xojo.com/issue/26060

so maybe compiler can also generate an isvalid method.

Greetings
Christian

Would “isa” returning “false” for an invalid weak delegate work? Or is that not the right idea?

Well, why not simply give all delegate classes properties. Like
TargetWeak as WeakRef
Target as object

which are non nil if appropriated.

Greetings
Christian

I ran into this problem today with a webapp. I was using WeakAddressOf to send a notification to a WebSession instance. But when a session is gone, there is no way to simply test if there is still something to invoke. You have to wrap the delegate call in a Try…Catch block. A simple test against nil, or a boolean method that return False if the delegate is no longer valid.

The feedback case #26060 seems to be private.

[quote=6630:@Joe Ranieri]See these posts:
http://www.realsoftware.com/listarchives/realbasic-nug/2011-03/msg01193.html
http://www.realsoftware.com/listarchives/realbasic-nug/2011-08/msg00432.html
[/quote]
Just for information these links are dead.

I have created a feature request: <https://xojo.com/issue/31185>
Implement a method to inform about wether a WeakAddressOf delegate can be invoked safely or not

Simply put: You have to get you into trouble if you want to avoid the trouble… Poor design indeed!

I think I put a couple of feedback requests for improvements to delegates. Like accessing the included reference to the object for the delegate. Maybe they can simply provide that as a variant property which may be the parent object or the weak ref to the parent object or nil if not applicable for the delegate.

Do you have some IDs to share. I’d like to favorite & follow them.

26060, 23305 and 20844.

Thanks Christian.
It seems that they all have been merged with the <https://xojo.com/issue/31185>. But I guess they are all private as I can’t see the merging notice in Feedback and Ssearching by their ID always leads to 31185.

Be aware with this issue that wrapping the Invoke in a Try/Catch will also catch exceptions caused inside the invoked method. If you don’t want that to happen, it means there is literally no way to code defensively.

I wonder if the delegate class contains simply a weak ref which we could access via Plugin until an official way is known.

Reverse engineering the memory layout is a violation of the EULA, if that’s what you were thinking of doing.

Of course. Sometimes I feel unhappy by having no way to add features or access internals without someone telling me about some EULA rules.

Maybe you can simply go and change it for r1, so we have a property on the delegate with the target object? Or expose the weakref object of the delegate. Or whatever you have there.
Or maybe use a InvalidDelegateTargetException instead of a NilObjectException.

Yes, a new exception type would help too. In my case, I’m writing code other developers will use, and I really do not want to catch their exceptions for them. Even if the NOE had a unique error number or something I could use to determine this was the reason, that would be good enough.

Since the internals can change poking around in the internals can be unreliable over time and we end up getting the bug reports about the plugins not working.
Far better to as k for a sanctioned API in the SDK or, in this case, something that you can test in user code without having to muck about with internals.

My vote: This really needs fixing : I gave up on using WeakDelegates altogether due to this issue.

WeakRefs and WeakAddressOf are objects. Should be great some way of temporally elevating it’s condition from Weak to “sustained” (go and add/subtract 1 to/from referenced object “ref counter”) like 2 methods like .hold() and .release() ?

// Current
Dim ref As WeakRef
If True Then
  Dim f As New FolderItem
  f.Name = "TestFile.txt"
  ref = New WeakRef(f)
  If ref.Value <> Nil Then
    MsgBox(FolderItem(ref.Value).Name) // This displays
  Else
    MsgBox("f is Nil.")
  End If
End If

If ref.Value <> Nil Then
  MsgBox(FolderItem(ref.Value).Name)
Else
  MsgBox("ref to f is gone.") // This displays
End If
// holding object example
Dim ref As WeakRef
If True Then
  Dim f As New FolderItem
  f.Name = "TestFile.txt"
  ref = New WeakRef(f)
  If ref.hold() Then // ref.hold() returns true if object life was held (ref counter +1), or false if it's already gone 
    MsgBox(FolderItem(ref.Value).Name) // This displays
  Else
    MsgBox("f is Nil, or referenced object is gone.")
  End If
End If

If ref.Value <> Nil Then
  MsgBox(FolderItem(ref.Value).Name) //Hey! it stills alive! We sustained a weak reference for a moment
Else
  MsgBox("Weird. You should never be here. You couldn't hold the object for some reason.")
End If
ref.release() // you are now free to go my object, bye. (ref counter -1)