Правильный способ избавиться от BackGroundWorker - PullRequest
47 голосов
/ 30 марта 2010

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

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

Ответы [ 5 ]

70 голосов
/ 30 марта 2010

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

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

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

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

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

13 голосов
/ 08 июля 2011

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

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

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

1 голос
/ 22 февраля 2012

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

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

worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandle(worker_RunWorkerCompleted);
worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
0 голосов
/ 30 марта 2010

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

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

ПК: -)

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

}
0 голосов
/ 30 марта 2010

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

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

...