Какой оптимальный интервал таймера? Служба .NET для Windows

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

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

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

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


person Nick    schedule 26.01.2010    source источник
comment
Что произойдет, если ваш таймер запускается каждые 10 секунд, но по какой-то причине для обработки запроса требуется 30 секунд?   -  person Raj More    schedule 26.01.2010
comment
Это полностью зависит от того, сколько времени требуется для выполнения шагов запроса и связи (только запрос, если база данных является локальной для службы), и насколько ресурсоемким является этот процесс.   -  person Jay    schedule 26.01.2010
comment
Я забыл упомянуть, что запрос к БД - это не единственное, что он делает, он также запускает процесс, который может занять несколько минут.   -  person Nick    schedule 26.01.2010
comment
@Raj - Если есть 6 элементов, которые нужно обработать, при первом запуске таймера он порождает поток, который забирает 3 элемента, и пока он их обрабатывает, если прошло еще 10 секунд, следующий поток возьмет следующие 3 Предметы. Как только предметы подобраны, они помечаются   -  person Nick    schedule 26.01.2010


Ответы (6)


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

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

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

person Steve Elmer    schedule 26.01.2010

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

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

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

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

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

person Alex Bagnolini    schedule 26.01.2010

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

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

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

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

person 3Dave    schedule 26.01.2010
comment
Именно так я это реализовал. Таким образом, ваш интервал таймера становится неактуальным для любых других соображений, кроме задержки пользовательского интерфейса. - ›Верно, но я не хочу заставлять пользователя ждать слишком долго. Если каждый поток выбирает 1 элемент, считается, что для обработки 3-го элемента потребуется минимум 30 секунд (в худшем случае), поэтому 3-й пользователь ждет так долго. Возможно, что все 3 запроса могут быть выполнены за 10 секунд, в этом случае было бы лучше, если бы один поток выбрал 3 элемента? - person Nick; 26.01.2010
comment
Я не согласен с тем, что лучше делать по три за раз. В идеале время выборки / обновления должно быть незначительным по сравнению с требуемым временем обработки. Я избегаю произвольного выбора X элементов, если это не приводит к значительному увеличению производительности. В приведенном выше примере пользовательский интерфейс может отображать элементы в процессе с каким-то вращающимся рабочим индикатором, что еще больше улучшает взаимодействие с пользовательским интерфейсом. Если у вас есть 3 потока на 3 ядрах, каждый элемент будет завершен почти одновременно. Надеюсь это поможет. - person 3Dave; 26.01.2010

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

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

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

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

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

person Chris Stavropoulos    schedule 26.01.2010
comment
Проблема с отправкой работы как части сообщения заключается в том, что, если служба не работает, текущая задача потенциально может быть потеряна. Кроме того, если служба обработки не может получить сообщение, она может никогда не узнать, что есть над чем поработать, в результате чего задачи, которые никогда не будут обработаны. Размещение очереди сообщений в центральном постоянном репозитории, например, в базе данных =), предотвращает эти проблемы. - person 3Dave; 26.01.2010
comment
Напротив. Если вы работаете с реальной службой обмена сообщениями, такой как MSMQ, это гарантированная доставка. Если служба не работает или не слушает, или в другом случае, она воспользуется ею при следующей возможности. - person Chris Stavropoulos; 27.01.2010

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

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

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

person Zyphrax    schedule 26.01.2010

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

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

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

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

person Rubens Farias    schedule 26.01.2010