2017-02-21 160 views
1

我加入处理程序申请:如何从应用程序中删除事件处理程序?

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

这个我想添加另一个处理程序

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

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

当我删除控制处理程序,我只是用:

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]); 
    } 

我怎样才能做同样的应用程序和应用程序域?

@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"); 
} 

,当我点击按钮,我得到两个消息。

+3

[C#中取消匿名方法(可能的重复http://stackoverflow.com/questions/183367/unsubscribe-anonymous-方法在C - 尖锐) – Pasick

+0

两个问题:1)当你想添加另一个处理程序?即在一些用户操作之后,或者在第一个处理程序被触发后2)你在哪里得到第二个处理程序的'param'? –

+0

@Pasick这不是100%重复,因为有一些关于Application.ThreadException的具体细节 – Andrey

回答

5

删除的处理程序,最好的办法是使用相同的处理器退订:

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

由于event本身在C#只是为add/remove方法的语法糖,还有来自退订没有通用的替代方法没有引用处理程序的事件。尤其是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; 
     } 
    } 
} 

看看这一行:current.threadExceptionHandler = value;

似乎只能有一个处理程序,订阅覆盖它。它不记录(MSDN不说一个有关此问题的话),但显然它是已知问题:

+0

是否可以取消订阅而不使用相同的处理程序? –

+0

@SergeyBerezovskiy在一般意义上没有。事件只是一对添加/删除方法。我正在查看ThreadException的具体内容,可以有一个特定的解决方案。 – Andrey

+0

只是想知道如果使用相同的处理程序是最好的方式,哪种方式是最好的方式? –

0

而不是使用LINQ的,使用活动方法。的 所以不是这样:

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

这样做:

Application.ThreadException += MyThreadExceptionHandler; 

.... 

public void MyThreadExceptionHandler(object sender, object a) 
{ 
    //your error handling code 
}