2013-11-15 7 views
4

Я пишу приложение, работающее с большой и уродливой сторонней системой через сложный API. Иногда в системе происходят некоторые ошибки, но если мы ожидаем, что моя программа столкнется с этими ошибками, может быть слишком поздно.Зачем использовать System.Threading.Thread.Sleep() - плохая практика?

Итак, я использую отдельный поток, чтобы проверить состояние системы следующим образом:

while (true) 
{ 
    ask_state(); 
    check_state(); 
    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1)); 
} 

Это действительно не имеет значения, если я проверить состояние системы один раз в 100 мс или один раз в минуту.

Но я слышал, что использование Thread.Sleep() - плохая практика. Зачем? И что я могу сделать в этой ситуации?

+0

Если вы хотите периодически проверять, почему бы не использовать таймер? – germi

+2

Главный вопрос: «Таймер лучше или нет? и почему Thread.Sleep() плохо? – user2862319

+1

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

ответ

5

Одна из причин заключается в том, что Thread.Sleep() блокирует ваш код от выполнения чего-либо еще. Последние усилия - сделать блокировку как можно меньше. Например, node.js является неблокирующим языком.

Обновление: Я не знаю об инфраструктуре Timer класс в C#. Возможно, это также блокирует.

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

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

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

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

+2

В этом случае он делает проверку в отдельном потоке – Polity

+0

Отдельная нить не означает, что она не блокирует. В течение этого времени другой поток будет переведен на удержание и не вернется в пул потоков, чтобы выполнить эту работу. –

+0

Да, это в отдельном потоке – user2862319

0

Я бы установил таймер на любые мс, которые вы хотите, и дождитесь завершения моих методов проверки, кстати, вы хотите использовать вечный цикл или это не полный код, который вы там показывали?
хорошо это пример того, что я говорю:

public void myFunction() 
{ 
int startCount = Environment.TickCount; 
ask_state(); 
check_state(); 

while (true) 
{ 
if (Environment.TickCount - startCount >= 20000) //two seconds 
{ 
break; 
} 
Application.DoEvents(); 
} 
} 

//Now you have an organized function that makes the task you want just call it every 
// time interval, again you can use a timer to do that for you 

private void timer_Tick(object sender, EventArgs e) 
{ 
      myFunction(); 
} 

удачи

+0

Если все в порядке, моя программа должна работать. И если он работает, он должен проверить состояние системы. Он будет изменен на время (запуск) в будущих выпусках – user2862319

+0

ok, поэтому просто используйте таймер вместо sleep(), вот пример того, о чем я говорю: – chouaib

3

Поскольку единственный способ, чтобы закрыть эту тему, если он ждет внутри Sleep является либо а) ждать Sleep, или b) использовать один из Thread.Abort или Thread.Interrupt.

Если это длинный сон, то (а) не подходит, если вы пытаетесь быть отзывчивыми. И (б) довольно неприятные, если код происходит до не Фактически, в то время как внутри Sleep.

Это намного лучше, если вы хотите, чтобы вы могли прерывать поведение сна подходящим способом, использовать ожидаемый объект (например,a ManualResetEvent) - тогда вы сможете разместить ожидание на ожидаемом объекте в условном выражении while, чтобы было ясно, что приведет к выходу потока.


Я использовать отключение в данном случае, потому что это очень распространенный сценарий, при котором требуется кросс-нить связи. Но для любой другой перекрестной сигнализации или связи могут применяться те же аргументы, и если это не shutdown, то Thread.Abort или Thread.Interrupt еще менее подходят.

+0

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

Смежные вопросы