【问题标题】:Hide ProgressChanged event隐藏 ProgressChanged 事件
【发布时间】:2013-04-26 17:52:15
【问题描述】:

是否可以在 backgroundworker 类中隐藏 ProgressChanged 事件?

我创建了一个继承 System.ComponentModel.BackgroundWorker 的类,我需要有多个事件:我的类处理一个对象列表,我需要(例如)在处理对象之前和之后有事件。我从 Backgroundworker 的 ProgressChanged 事件中触发这些事件,因为它是线程安全的。我调用ReportProgress 时调用的类中的方法然后使用该参数来确定要触发的事件。这行得通。

现在我想确保调用我的 Backgroundworker 的类不允许直接订阅ProgressChanged 事件。相反,它应该只能订阅我提供的其他事件。

【问题讨论】:

  • C# 为此使用了 private 关键字。将 BGW 封装在您的类中,并将实例变量设为私有。

标签: c# events backgroundworker


【解决方案1】:

有几种方法:

禁止订阅并禁止触发

子类可以写成 (a) 如果调用者尝试直接订阅 ProcessChange 事件,则抛出异常,并且 (b) 根本不引发事件。请注意,单独的 (a) 并不能阻止事件被订阅,因为调用者可以将子类转换为 BackgroundWorker 并直接订阅事件:

class ExtendedBackgroundWorker : BackgroundWorker
{
    public new event ProgressChangedEventHandler ProgressChanges
    {
        add { throw new InvalidOperationException("This event cannot be added directly"); }
        remove {}
    }

    protected override void OnProgressChanged(ProgressChangedEventArgs e)
    {
        // do not call base.OnProgressChanged
    }
}

使用组合代替继承

但是,如果可能,更好的方法可能是根本不从BackgroundWorker 继承。 BackgroundWorker 使用ProgressChanged 事件报告进度变化;如果它不这样做,它就不是BackgroundWorker。相反,请考虑将 BackgroundWorker 实现为私有类成员,并根据需要从成员中公开成员,例如:

class CustomBackgroundWorker : Component
{
    private BackgroundWorker worker;
    public event ProgressChangedEventHandler FirstEvent;
    public event ProgressChangedEventHandler SecondEvent;
    public event DoWorkEventHandler DoWork
    {
        add { worker.DoWork += value; }
        remove { worker.DoWork -= value; }
    }
    public event RunWorkerCompletedEventHandler RunWorkerCompleted
    {
        add { worker.RunWorkerCompleted += value; }
        remove { worker.RunWorkerCompleted -= value; }
    }

    public CustomBackgroundWorker()
    {
        worker = new BackgroundWorker();
        worker.ProgressChanged += OnProgressChanged;
        worker.WorkerReportsProgress = true;
    }

    public void RunWorkerAsync()
    {
        worker.RunWorkerAsync();
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        worker.Dispose();
    }

    private void OnProgressChanged(object o, ProgressChangedEventArgs e)
    {
        // code to handle progress change reports from the worker
    }
}

重新触发事件以供客户使用

子类可以将其与其他事件结合使用(而不是替代),而不是禁止使用该事件,以向订阅者提供相关信息(例如,总操作的进度)。

【讨论】:

  • "如果不这样做,它就不是 BackgroundWorker"。好点子,我一直在寻找快速获胜的机会,但绝对最好有一个干净的结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2011-08-31
  • 2014-06-09
  • 2018-05-13
相关资源
最近更新 更多