Допустимое использование Thread.Sleep () - PullRequest
8 голосов
/ 10 января 2012

Я работаю над консольным приложением, которое будет планироваться и запускаться с установленными интервалами, скажем, каждые 30 минут. Его единственное назначение - запросить веб-службу для обновления пакета строк базы данных.

API веб-службы рекомендует вызывать каждые 30 секунд и устанавливать тайм-аут после установленного интервала. Следующий псевдокод приведен в качестве примера:

listId := updateList(<list of terms>)
LOOP
  WHILE NOT isUpdatingComplete(listId)
END LOOP
statuses := getStatuses(“LIST_ID = {listId}”)

Я примерно закодировал это в C # как:

int callCount = 0;
while( callCount < 5 && !client.isUpdateComplete(listId, out messages) )
{
    listId = client.updateList(options, terms, out messages);
    callCount++;
    Thread.Sleep(30000);
}
// Get resulting status...

Можно ли в этой ситуации использовать Thread.Sleep ()? Я знаю, что это, как правило, не очень хорошая практика, но из прочтения причин не использовать это кажется приемлемым.

Спасибо.

Ответы [ 7 ]

6 голосов
/ 10 января 2012

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

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

5 голосов
/ 10 января 2012

Вообще говоря, Thread.Sleep подобен любому другому инструменту: его вполне можно использовать, за исключением случаев, когда он ужасно используется.Я не согласен с частью «не очень хорошая практика», которая является результатом того, что люди злоупотребляют Thread.Sleep, когда им нужно делать что-то еще (например, блокировать объект синхронизации).

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

3 голосов
/ 10 января 2012

Общее возражение против Sleep () состоит в том, что он тратит нить.

В вашем случае есть только 1 поток (возможно, 2), так что на самом деле это не проблема.

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

1 голос
/ 10 января 2012

вы можете придерживаться метода Thread.Sleep.Но было бы более элегантно планировать его запуск каждые 30 минут - так что вам не нужно заботиться об ожидании внутри приложения.

1 голос
/ 10 января 2012

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

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

0 голосов
/ 10 января 2012

Если вы блокируете поток на 30 минут, вы должны планировать задачу Windows каждые 30 минут, чтобы программа выполнялась, а затем заканчивалась. Таким образом, вы не блокируете поток так долго.

Для более коротких промежутков времени, например, 30 секунд / 1 минута, System.Thread.Sleep () прекрасно работает. Более 5 минут я бы использовал задачу Windows. (Я испанский, я думаю, что английская версия называется так, я говорю о задачах, которые вы планируете с панели управления ;-))

0 голосов
/ 10 января 2012

Thread.Sleep не является лучшим для выполнения периодической логики. Thread.Sleep (n) означает, что ваш поток откажется от управления на n миллисекунд. Нет гарантии, что он восстановит управление через n миллисекунд, это зависит от загрузки процессора.

...