У меня есть служба Windows, которая работает BackgroundWorker
и я задаюсь вопросом, делаю ли я правильную вещь, когда я останавливаю свою службу Windows.
Это достаточно к:
BackgroundWorker1_DoWork
завершенный метод (у меня есть некоторое время цикл в нем теперь, делая некоторые задачи), BackgroundWorker
, к null
Есть ли некоторый Dispose()
метод я должен звонить (Таким же образом Timer
класс имеет Timer.Dispose();
)?
Честно говоря, когда вы останавливаете службу windows - это не имеет значения. Ваш процесс win32 завершается, поэтому нет необходимости очищать ваши IDisposables. Любые неуправляемые ресурсы будут иметь финализатор, который все равно будет запущен.
Тем не менее, нормально иметь фоновый рабочий на уровне класса, который утилизируется, когда это делает класс e service. Это не обязательно, но всегда хорошо быть чистым.
Поскольку BackgroundWorker
реализует IDisposable
, вы должны утилизировать его, когда закончите с ним.
Вы упомянули, что это служба Windows, поэтому здесь есть несколько моментов. Когда вы останавливаете службу Windows, у вас есть около 30 секунд для возврата из метода OnStop
в вашей реализации ServiceBase
. Если вы не вернетесь в течение этого времени, Windows сообщает пользователю, что не может остановить службу. Что вы должны сделать, так это сигнализировать BackgroundWorker
, что вам нужно его остановить (с помощью механизма CancelAsync
), избавиться от рабочего и затем выйти. Однако, поскольку вы останавливаете службу, это не имеет особого значения, поскольку весь процесс в любом случае будет завершен , включая любые потоки, которые выполняются в нем.
Если вы сделаете то, что говорите, и дождитесь завершения рабочего процесса (в методе OnStop
), ваша служба может показаться пользователю, как будто она зависла, поскольку Windows скажет, что она не может остановите его, и процесс будет продолжаться.
Правильный метод - позволить рабочему потоку полностью завершить то, что он делает.
Это часто можно сделать, установив общий флаг \ waithandle \ что-то, что может быть использовано для связи с рабочим потоком (из основного потока), что он должен завершить то, что он делает, что естественным образом приведет к рабочему потоку перетасовывается из стопки и испаряется. Рабочий поток должен регулярно проверять «флаг», чтобы увидеть, нужно ли ему выйти (например, в вашем цикле), а основной поток службы может сигнализировать флагу, когда ему необходимо завершить работу. Затем основной поток ожидает завершения рабочего потока, например. вызывая соединение в рабочем потоке.
BackgroundWorker является IDisposable, поэтому вы должны утилизировать его, когда вам больше не нужно.
BackgroundWorkers также имеет метод CancelAsync, который изменяет свойство CancellationPending на true. Вы можете проверить это в своей функции DoWork, чтобы остановить ее выполнение.