Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to easilly see number of event subscriptions while debugging?

While debugging, can I look into textBox1.TextChanged to see the number of event subscriptions? If yes, then how do I drill to it? I need to know how many subscriptions there are at a given time for debugging because it looks like an event is triggered multiple times, but I suspect this bug is really because textBox1.TextChanged += handler is being mismanaged in the application, so there are too many subscribers.

Here is a simplified version of what I think is happening. If possible, I just want to set a breakpoint and count up the number of subscriptions to "textBox1.TextChanged":

private void textBox1_TextChanged(object sender, EventArgs e)
{
    textBox1.TextChanged += textBox1_TextChanged;
    MessageBox.Show("asdf");
    textBox1.TextChanged -= textBox1_TextChanged;        
    textBox1.Text = DateTime.Now.ToString();
    textBox1.TextChanged += textBox1_TextChanged;
}

Is that possible or is it more complicated?

like image 569
Madmartigan Avatar asked Jun 02 '14 21:06

Madmartigan


4 Answers

You will have to use Reflection to get to the invocation list of the event delegate:

    textBox1.TextChanged += textBox1_TextChanged;
    MessageBox.Show("asdf");
    textBox1.TextChanged -= textBox1_TextChanged;        
    textBox1.Text = DateTime.Now.ToString();
    textBox1.TextChanged += textBox1_TextChanged;
    var eventField = textBox1.GetType().GetField("TextChanged", BindingFlags.GetField
                                                               | BindingFlags.NonPublic
                                                               | BindingFlags.Instance);

    var subscriberCount = ((EventHandler)eventField.GetValue(textBox1))
                .GetInvocationList().Length;
like image 86
Volma Avatar answered Oct 14 '22 05:10

Volma


If you're only concerned with doing it under the debugger, rather than programmatically, then this is perhaps a simpler, non-invasive way:

class _24003458
{
    event EventHandler MyEvent;
    public void Test()
    {
        MyEvent += Handler1;
        MyEvent += Handler2;
        MyEvent(this, EventArgs.Empty);
    }
    void Handler1(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
    void Handler2(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

Put a breakpoint on either of the event handlers, and when it breaks, look at the Locals tab. The event, when expanded, will show the invocation count and event handlers:

Screenshot of program stopped at breakpoint and Locals window showing the expanded event with invocation count and handlers

like image 39
ClickRick Avatar answered Oct 14 '22 05:10

ClickRick


It is not possible with an event like this (for good reason), however, it is possable via reflection as Selman22 says, above) if you are using an event directly you can do so:

private event EventHandler handler;

var delegates = handler.GetInvocationList();
like image 44
BanksySan Avatar answered Oct 14 '22 06:10

BanksySan


You can create a member method which you add to the object which implements the INotifyPropertyChanged interface. It makes debugging very easy:

#if DEBUG
    public System.Delegate[] GetInvocationList()
    {
        return PropertyChanged?.GetInvocationList();
    }
#endif
like image 1
Jack Miller Avatar answered Oct 14 '22 05:10

Jack Miller