Подтвердить что ты не робот

Правильный способ утилизации BackGroundWorker

Будет ли это правильным способом избавиться от BackGroundWorker? Я не уверен, нужно ли удалять события перед вызовом .Dispose(). Также вызывается .Dispose() внутри делегата RunWorkerCompleted ok?

public void RunProcessAsync(DateTime dumpDate)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerAsync(dumpDate);
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // Do Work here
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
    worker.Dispose();
}
4b9b3361

Ответ 1

BackgroundWorker происходит от Component. Компонент реализует интерфейс IDisposable. Это в свою очередь заставляет BackgroundWorker наследовать метод Dispose().

Получение из Компонента является удобством для программистов Windows Forms, они могут отбросить BGW из панели инструментов в форму. Компоненты в целом, скорее всего, будут иметь что-то распоряжаться. Дизайнер Windows Forms позаботится об этом автоматически, загляните в файл Designer.cs для формы для поля "components". Его автоматически сгенерированный метод Dispose() вызывает метод Dispose() для всех компонентов.

Однако BackgroundWorker фактически не имеет члена, который требует утилизации. Он не переопределяет Dispose(). Его базовая реализация, Component.Dispose(), только гарантирует, что компонент будет удален из коллекции "components". И поднимите Disposed событие. Но иначе ничего не распоряжается.

Короче говоря: если вы сбросили BGW на форму, тогда все заботится автоматически, вам не нужно помогать. Если вы не отбросили его на форму, это не элемент в коллекции компонентов, и ничего не нужно делать.

Вам не нужно вызывать Dispose().

Ответ 2

Поздно к игре, но я просто столкнулся с сценарием, связанным с вашим вопросом, который, как я думал, я бы поделился. Если вы создаете своего работника на уровне класса и повторно используете его при последовательных операциях, не закрывая приложение, если вы не удаляете события после завершения, они будут увеличиваться и выполняться несколько раз при каждом последующем выполнении.

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork -= new DoWorkEventHandler(worker_DoWork);

Без вышеуказанного мой DoWork срабатывает один раз в первый раз, дважды во второй раз и т.д. Это, вероятно, не имеет большого значения для большинства, но мне потребовалось немного, чтобы понять это, поэтому, надеюсь, это поможет кому-то другому.

Ответ 3

worker.Dispose() не требуется, поскольку Dispose() автоматически вызывается. Но перед удалением объекта вам нужно удалить все обработчики событий.

Эта статья сообщает нам об этом.

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandle(worker_RunWorkerCompleted);
worker.DoWork -= new DoWorkEventHandler(worker_DoWork);

Ответ 4

Да, это кажется правильным. Конечно, одноразовые объекты лучше обрабатываются с помощью блоков using, но здесь у вас нет этой опции.

Я обычно создаю своих помощников по работе с жизненными циклами форм, повторно их использую и позволяю коду дизайнера обрабатывать удаление на форме. Меньше думать.

Ответ 5

Если это в форме "WinForms", пусть контейнер позаботится об этом (см. сгенерированный код Dispose в файле Form.Designer.xyz)

На практике я обнаружил, что вам может понадобиться создать экземпляр контейнера и добавить к нему рабочего (или другого сопутствующего), если кто-то знает более официальный способ сделать это кричать!

PK: -)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // watch the disposed event....
        backgroundWorker1.Disposed += new EventHandler(backgroundWorker1_Disposed);

        // try with and without the following lines
        components = new Container();
        components.Add(backgroundWorker1);
    }

    void backgroundWorker1_Disposed(object sender, EventArgs e)
    {
        Debug.WriteLine("backgroundWorker1_Disposed");
    }

//... from the Designer.xyz file ...

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

}