c# 通过反射从 BackgroundWorker.DoWork 中删除所有事件处理程序

c# remove all event handler from BackgroundWorker.DoWork by Reflection

我得到了帮助 link -How to remove all event handlers from a control

是的,我成功地从控件和表单中删除了所有事件处理程序。

但我在 BackgroundWorker 中失败了。

这是我的代码。

    void ReadingCompleted()
    {
        //find fields
        List<FieldInfo> liField=typeof(BackgroundWorker).GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Public).ToList();

        foreach(FieldInfo field in liField)
        {
            txtbox_log.Text += field.Name + "\r\n";
        }
        //below output list 
        //canCancelWorker
        //workerReportsProgress
        //cancellationPending
        //isRunning
        //asyncOperation
        //threadStart
        //operationCompleted
        //progressReporter
        //doWorkKey
        //runWorkerCompletedKey
        //progressChangedKey

        //remove all eventhandler
        object key = typeof(BackgroundWorker).GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);

        EventHandlerList events = (EventHandlerList)typeof(Component)
        .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
        .GetValue(this, null);
        events.RemoveHandler(key, events[key]);
        waitForm.Close();
    }

强烈建议不要编写这样的代码。一个设计良好的实现应该不需要任意删除订阅任何 class 的任何事件的所有处理程序,包括 DoWorkBackgroundWorker 的其他事件。唯一应该删除处理程序的代码与添加处理程序的代码相同,并且该代码知道它添加了什么处理程序,因此可以直接删除它。

就是说,假设您发布的代码是在继承了 BackgroundWorker class 的 class 中找到的,它对您不起作用的唯一原因是您尝试使用从 GetField("doWorkKey", ...) 调用返回的 FieldInfo 对象作为事件处理程序的实际键,实际上您应该调用该对象的 GetValue() 方法来获取实际键值。

正确的代码如下所示:

FieldInfo keyField = typeof(BackgroundWorker)
    .GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);
object key = keyField.GetValue(bw);

如果您发布的代码 不是 在继承 BackgroundWorker class 的 class 中(或者,即使它只是它不是您要修改的 BackgroundWorker 对象),那么您就会遇到第二个问题。您还需要在此处调用 GetValue() 方法时提供正确的 BackgroundWorker 实例:

EventHandlerList events = (EventHandlerList)typeof(Component)
    .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(this, null);

也就是说,不是将 this 传递给 GetValue() 方法,而是需要将引用传递给您尝试修改的实际 BackgroundWorker 对象。