Как правильно расположить BackgroundWorkers - PullRequest
6 голосов
/ 01 июня 2010

У меня есть служба Windows, которая запускает BackgroundWorker, и мне интересно, правильно ли я поступаю, когда останавливаю службу Windows.

Достаточно ли:

  1. Пусть метод BackgroundWorker1_DoWork завершится (у меня сейчас цикл while, я выполняю некоторые задачи)
  2. Установите переменную, которая содержит ссылку на BackgroundWorker, на null

Есть ли какой-нибудь метод Dispose(), который мне нужно вызвать (точно так же, как у класса Timer Timer.Dispose();)?

Ответы [ 4 ]

1 голос
/ 01 июня 2010

Поскольку BackgroundWorker реализует IDisposable, вы должны утилизировать его, когда закончите с ним.

Вы упоминаете, что это в службе Windows, поэтому здесь есть несколько вещей, которые вступают в игру. Когда вы останавливаете службу Windows, вы получаете около 30 секунд для возврата из метода OnStop в вашей реализации ServiceBase. Если вы не вернетесь в течение этого времени, Windows сообщит пользователю, что не может остановить службу. Что вы должны сделать, это сообщить BackgroundWorker, что вам нужно остановить его (используя механизм CancelAsync), избавиться от работника и выйти. Однако, поскольку вы останавливаете службу, на самом деле это не имеет значения, так как весь процесс будет остановлен в любом случае , включая все потоки, которые в нем работают.

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

1 голос
/ 01 июня 2010

Честно говоря, когда вы останавливаете службу Windows - это действительно не имеет значения. Процесс win32 завершен, поэтому нет необходимости обязательно очищать ваши IDisposables. Любые неуправляемые ресурсы будут иметь финализатор, который все еще будет работать.

Тем не менее, нормально иметь фонового работника на уровне класса, который будет утилизирован, когда это делает класс обслуживания. Не обязательно, но всегда хорошо быть чистым.

0 голосов
/ 01 июня 2010

BackgroundWorker является IDisposable, поэтому вы должны утилизировать его, когда вам больше не нужно.

BackgroundWorkers также имеет метод CancelAsync, который изменяет свойство CancellationPending на true. Вы можете проверить это в своей функции DoWork, чтобы остановить его запуск.

0 голосов
/ 01 июня 2010

Правильный метод - дать рабочему потоку аккуратно завершить то, что он делает.

Это часто можно сделать, используя общий флаг \ waithandle \ что угодно, что можно использовать для связи с рабочим потоком (из основного потока) о том, что он должен выйти из того, что он делает, что естественно приведет к рабочему потоку стаскивая свой стек и испаряясь. Рабочий поток должен регулярно проверять «флаг», чтобы увидеть, нужно ли ему выйти (например, в вашем цикле), а основной служебный поток может сигнализировать флаг, когда ему необходимо завершить работу. Затем основной поток ожидает выхода рабочего потока, например, вызвав соединение в рабочем потоке.

...