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!!!!");
}
source to share
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;
source to share
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.
source to share