如何从Application中删除事件处理程序?

Kli*_*Max 1 c#

我被添加到Application的处理程序:

Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, null);
Run Code Online (Sandbox Code Playgroud)

在此之后我想添加另一个处理程序

Application.ThreadException += (sender, a) => UnhandledExceptionsHelper.ApplicationOnThreadException(a, param);
Run Code Online (Sandbox Code Playgroud)

我如何删除以前的处理程序?

当我从Control中删除处理程序时,我只需使用:

    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]);
    }
Run Code Online (Sandbox Code Playgroud)

我如何使用Application和AppDomain做同样的事情?

@Andrey有我用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");
}
Run Code Online (Sandbox Code Playgroud)

当我点击按钮时,我收到两条消息.

And*_*rey 5

删除处理程序的最佳方法是使用相同的处理程序取消订阅:

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

因为event在C#中它本身只是add/ removemethods的语法糖,所以没有通用的替代方法来取消订阅没有引用处理程序的事件.特别是Application.ThreadException它变得更加怪异.我们来看看源代码:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

看看这个特定的行: current.threadExceptionHandler = value;

似乎只有一个处理程序,订阅会覆盖它.它没有记录(MSDN没有对这种行为说一句话),但显然它是已知的问题: