13

I've written some code to handle an event as follows:

AddHandler myObject.myEvent, AddressOf myFunction

It seemed that everything was working at first, but when I ran the debugger, I discovered that oftentimes, myFunction would run several times each time myObject.myEvent fired. I figured out that I had allowed the code to add the event handler to run more than once, resulting in this behavior.

Is there a way I can do something like this?

If myObject.myEvent is not handled Then
  AddHandler myObject.myEvent, AddressOf myFunction
End If
bdukes
  • 152,002
  • 23
  • 148
  • 175
Vivian River
  • 31,198
  • 62
  • 198
  • 313

8 Answers8

14

Assuming it's not your code that's publishing the event, you can't. The idea is that subscribers are isolated from each other - you can't find out about other event subscribers, raise the event yourself etc.

If the problem is that you're adding your own handler multiple times, you should be able to fix that yourself by keeping track of whether you have added a handler. Steven's idea of removing the handler before adding it is an interesting workaround: it's valid to attempt to remove a handler even when it isn't subscribed. However, I'd regard this as a workaround to your app not really knowing what it should be doing. It's a very quick short-term fix, but I'd be worried about leaving it in for the longer term.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
8

Either:

  1. Don't add your handler more than once.

  2. Attempt to remove the handler just prior to adding it.

Steven Sudit
  • 19,391
  • 1
  • 51
  • 53
  • if you attempt to remove the handler and it does not exist it will throw a nullreferenceexception – Sebastien Jan 14 '14 at 22:07
  • 3
    I though that it throws a null reference too, but that is not the case. The null error is thrown if the object does not exist. Remove Handler on myObject.myEvent, will throw error if myObject does not exist. – user1500403 Sep 06 '15 at 00:57
  • I use Leave and MouseDown events to turn on and off the events in my app. I found that if I fast clicked inside and outside of my control the events would get missed somehow due to lag or whatever and I would find my control getting the same handler added multiple times - Not sure exactly the reason. Either way it caused some crazy things and unexpected behavior to occur. Once I added in to my Leave event to first Remove the Handler prior to Adding it... all was fixed! Easy fix/hack. Thank you. – Code Novice Oct 08 '18 at 21:23
5

I know this is an old post but just wanted to add a solution for those who come looking in this direction...

VB.Net creates a special private member variable in the pattern of <YourEvent>Event that you can then use to test against Nothing.

Public Event MyClick As EventHandler

Private Sub OnMyClick()
    If MyClickEvent IsNot Nothing Then
        RaiseEvent MyClick(Me, New EventArgs())
    Else
        ' No event handler has been set.
        MsgBox("There is no event handler. That makes me sad.")
    End If
End Sub

Answer sourced from here: Determine if an event has been attached to yet

Community
  • 1
  • 1
hman
  • 486
  • 4
  • 7
4

There's no way to tell that a handler is already attached but you can safely call RemoveHandler on the event before calling AddHandler. If there isn't already a handler, RemoveHandler will have no effect.

Josh
  • 68,005
  • 14
  • 144
  • 156
  • The event member will only be null if there are no handlers attached at all. But there isn't a good way to tell if a specific handler is already hooked up. – Josh Jan 17 '14 at 15:38
  • I use Leave and MouseDown events to turn on and off the events in my app. I found that if I fast clicked inside and outside of my control the events would get missed somehow due to lag or whatever and I would find my control getting the same handler added multiple times - Not sure exactly the reason. Either way it caused some crazy things and unexpected behavior to occur. Once I added in to my Leave event to first Remove the Handler prior to Adding it... all was fixed! Easy fix/hack. Thank you. – Code Novice Oct 08 '18 at 21:24
2

Remove the handler and then add it. This way it will never be duplicated. Beware of the null reference error if your object does not exist. I got caught on that too and may happen when you are removing the handler outside the sub where the handler is created.

if not myObject is nothing then RemoveHandler myObject.myEvent, AddressOf myFunction
if not myObject is nothing then AddHandler myObject.myEvent, AddressOf myFunction
user1500403
  • 551
  • 8
  • 32
0

Save your event handler results to the database/session and then read them in again to check if event has already been handled.

Kon
  • 27,113
  • 11
  • 60
  • 86
0

I know I am a few years late to the game but you could always scope a class variable and then set it after the fact. This is not a totally hardened way of doing things but it is better than just hoping you did not have something or re adding it every time. In my case I used this in a WinForms app were I wanted to add a handler for dragging and dropping onto a datagridview surface. I wanted to stop this functionality if part of another datagridview was not yet filled out completely that it was dependent on.

So it would be like this:

Class level

Private _handlersAdded As Boolean = False

Constructor:

Public Sub New()
  AddHandler dgv.DragEnter, AddressOf DragEnter
  _handlersAdded = True
End Sub

Method that determines issue:

Private Sub CheckRowsAreDone()
  For Each row As DataGridViewRow In dgv.Rows
    Dim num = 0

    For i = 0 To row.Cells.Count - 1
      Dim val = If(Not String.IsNullOrEmpty(row?.Cells(i)?.Value?.ToString), 1, -1)
      num += val
    Next

    If num > -(row.Cells.Count) And num < (row.Cells.Count) Then
      RemoveHandler dgv.DragEnter, AddressOf DragEnter
      _handlersAdded = False
      Exit Sub
    End If

    If Not _handlersAdded Then
      AddHandler dgv.DragEnter, AddressOf DragEnter
      _handlersAdded = True
    End If

    Next
End Sub
djangojazz
  • 14,131
  • 10
  • 56
  • 94
-3

You may use IsHandleCreated property to check your event already has an handle or not.

  If e.Control.IsHandleCreated = False Then
            AddHandler e.Control.KeyPress, AddressOf TextBox_keyPress
  End If
Muhammad Saqib
  • 2,185
  • 3
  • 35
  • 48