1

I was added handler to Application:

Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, null);

After this i want to add another handler

Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, param);

How can i remove previous handler?

When i delete handlers from Control i just use:

    public void RemoveOnThreadException(SimpleButton b)
    {
        FieldInfo f1 = typeof(Control).GetField("EventClick",
            BindingFlags.Static | BindingFlags.NonPublic);
        object obj = f1.GetValue(b);
        PropertyInfo pi = b.GetType().GetProperty("Events",
            BindingFlags.NonPublic | BindingFlags.Instance);
        EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
        list.RemoveHandler(obj, list[obj]);
    }

How can i do the same with Application and AppDomain?

@Andrey there is my tries with Button.Click:

public TestForm()
{
    InitializeComponent();
    simpleButton1.Click += (sender, a) => simpleButton1_Click(sender,a);
    simpleButton1.Click -= simpleButton1_Click;
    simpleButton1.Click += (sender, a) => simpleButton1_Click(sender, a);
}

private void simpleButton1_Click(object sender, EventArgs e)
{
   MessageBox.Show("Hi");
}

And when i click button i got two Messages.

Kliver Max
  • 5,107
  • 22
  • 95
  • 148
  • 3
    Possible duplicate of [Unsubscribe anonymous method in C#](http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c-sharp) – Pasick Feb 21 '17 at 10:16
  • Two questions: 1) when you want to add another handler? i.e. after some user action, or after first handler fired 2) where you get `param` for second handler? – Sergey Berezovskiy Feb 21 '17 at 10:27
  • @Pasick this is not 100% dup because there are some specifics regarding Application.ThreadException – Andrey Feb 21 '17 at 10:30
  • @SergeyBerezovsky I add second handler just after i create `params`. And use first handler with `null` instead `params` just couse `params` do not exists when first heandler was added. – Kliver Max Feb 21 '17 at 10:35

2 Answers2

5

The best way to remove the handler is to unsubscribe using the same handler:

ThreadExceptionEventHandler handler = (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, null);
Application.ThreadException += handler;
//Later...
Application.ThreadException -= handler;

Since event itself in C# is just syntax sugar for add/remove methods, there is no general alternative way to unsubscribe from an event without a reference to a handler. Specifically with Application.ThreadException it gets even weirder. Let's look at the source code:

https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Application.cs,8243b844777a16c3,references

public static event ThreadExceptionEventHandler ThreadException {
    add {
        Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "AffectThreadBehavior Demanded");
        IntSecurity.AffectThreadBehavior.Demand();

        ThreadContext current = ThreadContext.FromCurrent();
        lock(current) {                    
            current.threadExceptionHandler = value;
        }
    }
    remove {
        ThreadContext current = ThreadContext.FromCurrent();
        lock(current) {
            current.threadExceptionHandler -= value;
        }
    }
}

Look at this particular line: current.threadExceptionHandler = value;

It seems that there can be only one handler, and subscribing overrides it. It is not documented (MSDN doesn't say a word about this behavior), but apparently it is known issue:

Andrey
  • 59,039
  • 12
  • 119
  • 163
  • Is it possible to unsubscribe WITHOUT using same handler? – Sergey Berezovskiy Feb 21 '17 at 10:14
  • @SergeyBerezovskiy in general sense no. Event is just a pair of add/remove methods. I am looking what is behind ThreadException specifically, there can be a particular solution. – Andrey Feb 21 '17 at 10:17
  • Just wonder if using same handler is the best way, which way is the second after best? – Sergey Berezovskiy Feb 21 '17 at 10:22
  • @Andrey when i tried `-=` with button.Click even its not helped me. I mean i add handler first time after remove handler, and after again add handler. And saw that handler fires twice. – Kliver Max Feb 21 '17 at 10:24
  • @SergeyBerezovskiy there is no really second best. This is the way. The alternative is to write highly unreliable code that will dig with reflection. I would not do it unless it was life and death situation. – Andrey Feb 21 '17 at 10:24
  • @KliverMax post the code please, it must work because it is how it is supposed to work in C# – Andrey Feb 21 '17 at 10:24
  • @KliverMax you are doing it wrong. Lambda expression produces a new function. You don't actually need a lamba here, just subscribe and unsubscribe your method directly and it will work. – Andrey Feb 21 '17 at 10:51
  • @Andrey i just tried your code and its works. Thanks! – Kliver Max Feb 21 '17 at 11:09
0

Instead of using the Events with LINQ, use Methods. So instead of doing this:

Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, null);

Do this:

Application.ThreadException += MyThreadExceptionHandler;

 ....

public void MyThreadExceptionHandler(object sender, object a)
{
    //your error handling code
}
mrousavy
  • 311
  • 1
  • 8