Каков оптимальный интервал таймера? .NET Windows Service - PullRequest
2 голосов
/ 26 января 2010

У меня есть служба Windows .NET, в которой установлен таймер с интервалом 10 секунд. Каждые 10 секунд он запрашивает базу данных о любой работе, которая выбирается, выбирает 3 верхних рабочих элемента и обрабатывает их. Время, необходимое для обработки каждого рабочего элемента, будет зависеть от пользователя. Это может варьироваться от нескольких секунд до нескольких минут.

Мне кажется, что 10 секунд слишком мало. Я выбрал низкий интервал, так как пользователь ожидает завершения процесса (они видят индикатор выполнения во внешнем интерфейсе), и чем быстрее сервис забирает работу, тем лучше. Кроме того, количество рабочих элементов (три) было выбрано случайным образом.

В моем коде действительно есть "lock (this)", чтобы один поток не перешагнул через другой. Можно ли использовать в производственной среде небольшую продолжительность 10 секунд?

РЕДАКТИРОВАТЬ: Кроме того, имеет ли смысл, что я выбираю только 3 элемента каждый раз для обработки.

Ответы [ 6 ]

1 голос
/ 27 января 2010

... Кроме того, имеет ли смысл, что я выбираю только 3 элемента каждый раз для обработки ...

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

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

1 голос
/ 26 января 2010

Ваш интервал обслуживания должен быть независимым от пользовательского интерфейса. Одним из способов достижения этого является наличие флага для каждого рабочего элемента в вашей базе данных, который помечает их как «новые», «в процессе» или «выполнено». Пусть ваш сервис забирает по одному предмету за раз и помечает его как «в процессе», делает все, что ему нужно, и помечает его как «выполненный» после завершения.

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

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

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

1 голос
/ 26 января 2010

Я сейчас обрабатываю что-то подобное на работе, основной таймер выбирает из хранимой процедуры работу, выполняемую каждую секунду (1000 мс).

Хотя выборка не ограничивается элементами X (например, 3 в вашем примере).
Я просто добавляю столько потоков, сколько нужно, и позволяю фреймворку правильно их обрабатывать.

Я пытался отделить весь код так, чтобы мне не нужно было использовать lock.

Я сохраняю в БД всю информацию журнала, и у меня есть другой таймер (с интервалом 30 минут), который в конечном итоге извлекает ошибки и отправляет их мне.

У вас не должно быть проблем с 1-секундным таймером, если вы передаете всю работу другому потоку, отличному от таймера.

0 голосов
/ 26 января 2010

Трудно ответить на вопросы; ваша производственная среда может иметь аппаратную конфигурацию больше, чем ваша сравнительная среда, поэтому ваша очередь может обрабатываться быстрее, чем текущие значения.

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

Самая важная вещь - убедиться, что вы не получите больше рабочих элементов, пока у вас есть работа ..

Кстати, вы должны прочитать это: Почему блокировка (это) плоха .

0 голосов
/ 26 января 2010

Я бы использовал интервал в 10 секунд.
Сделайте еще одну проверку, когда пользовательский процесс завершится (чтобы избежать ненужного 10-секундного ожидания)

Вы можете заглянуть в класс SQLDependency, чтобы перехватывать события базы данных. Это было бы еще лучше, но немного сложнее реализовать.

Для получения дополнительной информации о SQLDependecy смотрите здесь:
http://www.codeproject.com/KB/database/chatter.aspx

0 голосов
/ 26 января 2010

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

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

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

Если вы заинтересованы в обмене сообщениями, загляните в NServiceBus. По сути, это оболочка для MSMQ, которая откроет вам новый мир идей о взаимосвязанных системах.

Варианты действительно бесконечны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...