Below is my code, first is where I raise the event and second section is where I consume it in another class. It seems pretty straight forward, but the logs are showing that even though the event is raised once, the event is firing 20+ times on the class that consumes this 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);
}
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!!!!");
}
Try this, this will unregister any prev subscriber:
ibSerialPort.OnPacketReceived -= ibSerialPort_OnPacketReceived; // unregister
ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived; //register
How many times is this being called? If this gets called multiple times then your event will be called multiple times.
ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;
As a test, you could remove the delegate just before you add it:
ibSerialPort.OnPacketReceived -= ibSerialPort_OnPacketReceived;
ibSerialPort.OnPacketReceived += ibSerialPort_OnPacketReceived;
I wonder if your class that defines ibSerialPort_OnPacketReceived
is used (even in separated instances) 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. A reference to the subscription is held even though it appears I've released the handle to it. This is due to how delegates keep a list of their subscribers.
If this is the problem, you'll need to unsubscribe each time:
es.MyEvent -= s.OnEvent
This should be done before you lose your handle to your subscriber (i.e. before s
is out of scope or null
). You could consider keeping track of your event source in the subsriber, and have a Dispose
method that unsubscribes for you.
Also, as others have noted, you could unsubscribe before subscribing :) I'm sure by now you have the solution you need.
I had the same problem, register your event in a synchronous method ( I put it in form_loaded)
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
RefreshHierarchy.COIDConflict += RefreshHierarchy_COIDConflict;
}