检查对象中是否存在特定事件的事件处理程序

3
我已在for循环中使用以下代码片段。
DataTable childTable = dataTable.DataSet.Relations[relationName].ChildTable;

if (childTable != null)
{
   iBindingList = childTable.AsDataView() as IBindingList;
   iBindingList.ListChanged += new ListChangedEventHandler(GridDataRecord_ListChanged);
}

在这种情况下,我需要检查iBindinglist对象是否已经调用了listchanged事件。您能否查看并提供建议以实现此目的。谢谢提前。
敬礼, Rajasekar
2个回答

8

无法确定您的处理程序是否已经添加。幸运的是,您不需要这样做。

iBindingList.ListChanged -= GridDataRecord_ListChanged;
iBindingList.ListChanged += GridDataRecord_ListChanged;

假设类是良好的行为(在这种情况下,您应该能够相信类是良好的行为),即使未添加,也可以安全地删除GridDataRecord_ListChanged。删除它只会什么都不做。如果您只在删除处理程序后添加处理程序,则永远不会多次添加它。

1
你可以在附加处理程序之前删除处理程序。
if (childTable != null)
{
   iBindingList = childTable.AsDataView() as IBindingList;
   iBindingList.ListChanged -= new ListChangedEventHandler(GridDataRecord_ListChanged);
   iBindingList.ListChanged += new ListChangedEventHandler(GridDataRecord_ListChanged);
}

如果您正在运行单线程环境并且始终像这样附加事件,则应该没问题。但是,如果有多个线程,则可能会存在竞争条件。如评论中所述,如果有多个线程附加相同的委托,则存在此问题。 -= 仅删除最后一个委托,因此多个添加和单个删除将意味着事件仍然附加。
或者,可以设置一个标志来检查是否已订阅事件。
bool listChangedSubscribed = false;  
if (childTable != null)
{
   iBindingList = childTable.AsDataView() as IBindingList;
   iBindingList.ListChanged -= new ListChangedEventHandler(GridDataRecord_ListChanged);
   if(!listChangedSubscribed)
   {
       iBindingList.ListChanged += new ListChangedEventHandler(GridDataRecord_ListChanged);
       listChangedSubscribed = true; 
   }

1
多线程的问题提得很好,我在回答中忘记了这一点。需要明确的是,如果有多个线程使用相同的iBindingList,并不重要,只有当有多个线程尝试添加完全相同的委托时才会产生影响。 - user743382
对于澄清加1。"-="仅删除最后一个委托,因此多个添加和单个删除将意味着事件仍然附加。 - keyboardP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接