Вопрос по c#, timer – Таймер C # или Thread.Sleep

44

Я запускаю службу Windows и использую цикл и Thread.Sleep для повторения задачи. Было бы лучше использовать метод таймера?

Если да, то пример кода был бы отличным

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

int curMinute;
int lastMinute = DateTime.Now.AddMinutes(-1).Minute;

while (condition)
{
   curMinute = DateTime.Now.Minute;

   if (lastMinute < curMinute) {
         // do your once-per-minute code here
         lastMinute = curMinute;
   }

   Thread.Sleep(50000);      // sleeps for 50 seconds

   if (error condition that would break you out of this) {
       break;      // leaves looping structure
   }
}

Ваш Ответ

11   ответов
11

что ваш код будет находиться в режиме ожидания в течение 50 секунд между окончанием одного цикла и началом следующего ...

Таймер будет вызывать ваш цикл каждые 50 секунд, что не совсем то же самое.

Они оба действительны, но, вероятно, вы ищете здесь таймер.

2

   if (error condition that would break you out of this) {
       break;      // leaves looping structure
   }

Вы, вероятно, должны иметь

while(!error condition)

Кроме того, я бы пошел сTimer.

43

ИМО. Таким образом, если ваш сервис попросят остановить, он может очень быстро отреагировать на это и просто не вызывать обработчик тиковых отметок таймера снова ... если вы спите, менеджеру сервиса придется подождать 50 секунд или убить ваш нить, ни одна из которых не очень приятно.

Чтобы избежать уничтожения потока, вы можете использовать ManualResetEvent.WaitOne (50000) вместо Thread.Sleep (). Затем вы можете установить () дескриптор ожидания, чтобы сигнализировать потоку о необходимости завершить его при первой возможности. Таймер, вероятно, все еще предпочтительнее в этом случае.
-1

что сон - лучшая реализация с конечным автоматом. Это по-прежнему будет держать вас под контролем приложения в любое время, но позволит любой ответ, необходимый в любое конкретное время. Это также будет обрабатывать обратные вызовы таймера, которые короче, чем «время выполнения обработки в цикле»;

Например..

<!-- language: c# -->
public enum State
{
    Idle = 0,
    Processing = 1,
    Stop = 100,
}
public void Run()
{
    State state = State.Idle;   // could be a member variable, so a service could stop this too

    double intervalInSeconds = 60;
    System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
    while (state != State.Stop)
    {
        switch (state)
        {
            case State.Idle:
                {
                    if (nextExecution > System.DateTime.Now)
                    {
                        state = State.Processing;
                    }
                }
                break;
            case State.Processing:
                {
                    // do your once-per-minute code here

                    // if you want it to stop, just set it state to stop.
                    // if this was a service, you could stop execution by setting state to stop, also
                    // only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways

                    state = State.Idle;
                    nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
                }
                break;
            default:
                break;
        }

        System.Threading.Thread.Sleep(1);
    }
}
Это проблема с наивнымSleep реализация, которую вы улучшаете. Это даже не проблема вTimer решение на основе; Вы не определяете интервал ожидания, вы определяете интервал времени, когда нужно инициировать событие, поэтому вообще не нужно определять, как долго ждать.
И какое преимущество вы чувствуете, спящий добавляет по сравнению с использованием таймера. Ряд других указал на недостатки сна, которые вы не рассмотрели.
Мой взгляд заключается в том, чтобы постоянно контролировать приложение, потому что сон и / или длительный таймер не позволят вам обрабатывать вещи с интервалами, меньшими, чем выбранный период ожидания.
1

или любой, в зависимости от ситуации.

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

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

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

Это возможно, если вы не используете семафор.
+1 за указание, что при использовании таймера кодcould быть запущенным несколько раз одновременно.
31
class Program
{
    static void Main(string[] args)
    {
        Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000);
        Console.Read();
        timer.Dispose();
    }

    public static void TimeCallBack(object o)
    {
      curMinute = DateTime.Now.Minute;
      if (lastMinute < curMinute) {
       // do your once-per-minute code here
       lastMinute = curMinute;
    }
}

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

Sleep() легко, понятно и короче в реализации.

4

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

7

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

1

см вопрос здесь) и я теперь использовалDispatchTimer на основании полученных ответов.

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

+1 первым упомянуть DispatchTimer
0

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

Код @Prashanth должен быть именно тем, что вам нужно.

Похожие вопросы