Как вызвать метод ежедневно, в определенное время, в C #? - PullRequest
69 голосов
/ 14 июля 2010

Я искал на SO и нашел ответы о Quartz.net. Но он кажется слишком большим для моего проекта. Я хочу эквивалентное решение, но более простое и (в лучшем случае) в коде (внешняя библиотека не требуется). Как я могу вызвать метод ежедневно, в определенное время?

Мне нужно добавить информацию об этом:

  • Самый простой (и безобразный) способ сделать это - проверять время каждую секунду / минуту и ​​вызывать метод в нужное время

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

Я нашел это решение Вызов метода в фиксированное время в Java в Java. Есть ли аналогичный способ в C #?

РЕДАКТИРОВАТЬ: Я сделал это. Я добавил параметр в void Main () и создал bat (запланированный Windows Task Scheduler) для запуска программы с этим параметром. Программа запускается, выполняет работу, а затем завершает работу. Если работа не удалась, она может написать журнал и отправить электронную почту. Этот подход хорошо соответствует моим требованиям:)

Ответы [ 14 ]

0 голосов
/ 15 апреля 2019

Я нашел это очень полезным:

using System;
using System.Timers;

namespace ScheduleTimer
{
    class Program
    {
        static Timer timer;

        static void Main(string[] args)
        {
            schedule_Timer();
            Console.ReadLine();
        }

        static void schedule_Timer()
        {
            Console.WriteLine("### Timer Started ###");

            DateTime nowTime = DateTime.Now;
            DateTime scheduledTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 8, 42, 0, 0); //Specify your scheduled time HH,MM,SS [8am and 42 minutes]
            if (nowTime > scheduledTime)
            {
                scheduledTime = scheduledTime.AddDays(1);
            }

            double tickTime = (double)(scheduledTime - DateTime.Now).TotalMilliseconds;
            timer = new Timer(tickTime);
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }

        static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("### Timer Stopped ### \n");
            timer.Stop();
            Console.WriteLine("### Scheduled Task Started ### \n\n");
            Console.WriteLine("Hello World!!! - Performing scheduled task\n");
            Console.WriteLine("### Task Finished ### \n\n");
            schedule_Timer();
        }
    }
}
0 голосов
/ 26 июня 2018

24 часа

1002 *
0 голосов
/ 05 января 2017

У меня простой подход к этому.Это создает задержку в 1 минуту до того, как действие произойдет.Вы также можете добавить секунды, чтобы сделать Thread.Sleep ();короче.

private void DoSomething(int aHour, int aMinute)
{
    bool running = true;
    while (running)
    {
        Thread.Sleep(1);
        if (DateTime.Now.Hour == aHour && DateTime.Now.Minute == aMinute)
        {
            Thread.Sleep(60 * 1000); //Wait a minute to make the if-statement false
            //Do Stuff
        }
    }
}
0 голосов
/ 18 декабря 2015

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

Например, если вы хотите сделать что-то через 60 минут, таймерыинтервалы будут приблизительно:

30: 00: 00, 15:00:00, 07:30:00, 03:45:00, ..., 00:00:01, RUN!

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

(преобразовано из VB.NET)

autoRestartThread = new System.Threading.Thread(autoRestartThreadRun);
autoRestartThread.Start();

...

private void autoRestartThreadRun()
{
    try {
        DateTime nextRestart = DateAndTime.Today.Add(CurrentSettings.AutoRestartTime);
        if (nextRestart < DateAndTime.Now) {
            nextRestart = nextRestart.AddDays(1);
        }

        while (true) {
            if (nextRestart < DateAndTime.Now) {
                LogInfo("Auto Restarting Service");
                Process p = new Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.Arguments = string.Format("/C net stop {0} && net start {0}", "\"My Service Name\"");
                p.StartInfo.LoadUserProfile = false;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                p.StartInfo.CreateNoWindow = true;
                p.Start();
            } else {
                dynamic sleepMs = Convert.ToInt32(Math.Max(1000, nextRestart.Subtract(DateAndTime.Now).TotalMilliseconds / 2));
                System.Threading.Thread.Sleep(sleepMs);
            }
        }
    } catch (ThreadAbortException taex) {
    } catch (Exception ex) {
        LogError(ex);
    }
}

Примечание. Я установил минимальный интервал в 1000 мс, его можно увеличитьуменьшается или удаляется в зависимости от требуемой точности.

Не забудьте также остановить поток / таймер при закрытии приложения.

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