C # event handler gets called multiple times when event occurs once

Below is my code, firstly I raise the event and the second section is where I use it in another class. It looks pretty straight forward, but the logs show that even if the event is raised once, the event is fired more than 20 times in the class that is consuming the event. Any ideas?

IBSerialPort

class:

public delegate void PacketReceivedHandler(object sender, PacketReceivedEventArgs e);
public event PacketReceivedHandler OnPacketReceived;

public class PacketReceivedEventArgs : EventArgs
{
  public Packet PacketReceived { get; private set; }

  public PacketReceivedEventArgs(Packet packet)
  {
    PacketReceived = packet;
  }
}

// raise event
if (OnPacketReceived != null)
{
    Log("This is only called ONCE!");
    PacketReceivedEventArgs args = new PacketReceivedEventArgs(data);
    OnPacketReceived(this, args);
}

      

The class that uses IBSerialPort

and consumes its OnPacketReceived

Event:

IBSerialPort ibSerialPort = null;
..
if (ibSerialPort == null)
{
  Log("This is only called once");

  ibSerialPort = IBSerialPort.Instance;

  ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;
}

void ibSerialPort_OnPacketReceived(object sender, IBSerialPort.PacketReceivedEventArgs args)
{
   Log("This is called ~25 times!!!!");
}

      

+3


source to share


4 answers


Try this, this will unregister any previous caller:



ibSerialPort.OnPacketReceived -= ibSerialPort_OnPacketReceived;   // unregister
ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;  //register

      

+5


source


How many times is it called? If this is called multiple times, your event will be called multiple times.

 ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;

      



As a test, you can remove the delegate just before adding it:

ibSerialPort.OnPacketReceived -= ibSerialPort_OnPacketReceived;
ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;

      

+4


source


I wonder if your class that defines ibSerialPort_OnPacketReceived

is used (even in isolated cases) 25 times and you think you are releasing it. Consider this code:

class EventSender
{
    public Action MyEvent;
}

class Subscriber
{
    public void OnEvent()
    {
        Console.WriteLine("OnEvent");
    }
}

class Program
{
    static void Main(string[] args)
    {
        EventSender es = new EventSender();

        Subscriber s = new Subscriber();
        es.MyEvent += s.OnEvent;

        s = new Subscriber();
        es.MyEvent += s.OnEvent;

        es.MyEvent();

        Console.ReadKey();
    }
}

      

Here "OnEvent" will be printed twice. The subscription link is preserved, although it looks like I released it. This has to do with the way delegates keep their list of subscribers.

If this is a problem, you need to unsubscribe every time:

es.MyEvent -= s.OnEvent

      

This must be done before you lose your descriptor to your subscriber (i.e. before going s

out of scope or null

). You might consider tracking down the event source in the subscriber and using a method Dispose

that is not subscribed to.

Also, as others have pointed out, you can unsubscribe before subscribing :) I'm sure you have the solution you need by now.

+1


source


I had the same problem, register your event with a synchronous method (I put it in form_loaded)

    private async void Window_Loaded(object sender, RoutedEventArgs e)
    {
        RefreshHierarchy.COIDConflict += RefreshHierarchy_COIDConflict;
    }

      

0


source







All Articles