Как использовать class .NET Timer для запуска события в определенное время?

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

Как насчет чего-то подобного, используя class System.Threading.Timer ?

 var t = new Timer(TimerCallback); // Figure how much time until 4:00 DateTime now = DateTime.Now; DateTime fourOClock = DateTime.Today.AddHours(16.0); // If it's already past 4:00, wait until 4:00 tomorrow if (now > fourOClock) { fourOClock = fourOClock.AddDays(1.0); } int msUntilFour = (int)((fourOClock - now).TotalMilliseconds); // Set the timer to elapse only once, at 4:00. t.Change(msUntilFour, Timeout.Infinite); 

Обратите внимание: если вы используете System.Threading.Timer , обратный вызов, указанный TimerCallback будет выполняться в streamе пула streamов (non-UI), поэтому, если вы планируете что-то делать с вашим интерфейсом в 4:00, (например, с помощью Control.Invoke в приложении Windows Forms или Dispatcher.Invoke в приложении WPF).

Начиная с .NET 4.5 существует действительно чистое решение:

 public async void ScheduleAction(Action action, DateTime ExecutionTime) { await Task.Delay((int)ExecutionTime.Subtract(DateTime.Now).TotalMilliseconds); action(); } 

Вот решение без async / wait:

 public void Execute(Action action, DateTime ExecutionTime) { Task WaitTask = Task.Delay((int)ExecutionTime.Subtract(DateTime.Now).TotalMilliseconds); WaitTask.ContinueWith(_ => action); WaitTask.Start(); } 

Следует отметить, что это работает только около 24 дней из-за значения int32 max, чего достаточно для вашего случая, но стоит отметить.

Вы можете использовать Task Sceduler в windowsх. Смотрите подробный пример триггера .

или используйте следующий код, если вы хотите написать его самостоятельно:

 public void InitTimer() { DateTime time = DateTime.Now; int second = time.Second; int minute = time.Minute; if (second != 0) { minute = minute > 0 ? minute-- : 59; } if (minute == 0 && second == 0) { // DoAction: in this function also set your timer interval to 24 hours } else { TimeSpan span = //new daily timespan, previous code was hourly: new TimeSpan(0, 60 - minute, 60 - second); timer.Interval = (int) span.TotalMilliseconds - 100; timer.Tick += new EventHandler(timer_Tick); timer.Start(); } } void timer_Tick(object sender, EventArgs e) { timer.Interval = ...; // 24 hours // DoAction } 

Принимая во внимание VoteCoffees, вот компактное решение, основанное на событиях:

 public class DailyTrigger { readonly TimeSpan triggerHour; public DailyTrigger(int hour, int minute = 0, int second = 0) { triggerHour = new TimeSpan(hour, minute, second); InitiateAsync(); } async void InitiateAsync() { while (true) { var triggerTime = DateTime.Today + triggerHour - DateTime.Now; if (triggerTime < TimeSpan.Zero) triggerTime = triggerTime.Add(new TimeSpan(24,0,0)); await Task.Delay(triggerTime); OnTimeTriggered?.Invoke(); } } public event Action OnTimeTriggered; } 

Потребитель: `

 void Main() { var trigger = new DailyTrigger(16); // every day at 4:00pm trigger.OnTimeTriggered += () => { // Whatever }; Console.ReadKey(); } 

Планировщик задач является лучшим вариантом, и его можно легко использовать в C #, http://taskscheduler.codeplex.com/

Я сделал так, чтобы каждое утро уволить 7 утра

 bool _ran = false; //initial setting at start up private void timer_Tick(object sender, EventArgs e) { if (DateTime.Now.Hour == 7 && _ran==false) { _ran = true; Do_Something(); } if(DateTime.Now.Hour != 7 && _ran == true) { _ran = false; } } 

Решение Echo to Dan, использующее Timercallback, является быстрым и опрятным решением. Внутри метода, который вы хотите запланировать выполнение задачи или подпрограммы, используйте следующее:

  t = New Timer(Sub() 'method call or code here' End Sub, Nothing, 400, Timeout.Infinite) 

использование «Timeout.Infinite» гарантирует, что обратный вызов будет выполняться только один раз после 400 мс. Я использую VB.Net.

Как насчет этого решения?

 Sub Main() Dim t As New Thread(AddressOf myTask) t.Start() Console.ReadLine() End Sub Private Sub myTask() Dim a = "14:35" Dim format = "dd/MM/yyyy HH:mm:ss" Dim targetTime = DateTime.Parse(a) Dim currentTime = DateTime.Parse(Now.ToString(format)) Console.WriteLine(currentTime) Console.WriteLine("target time " & targetTime) Dim bb As TimeSpan = targetTime - currentTime If bb.TotalMilliseconds < 0 Then targetTime = targetTime.AddDays(1) bb = targetTime - currentTime End If Console.WriteLine("Going to sleep at " & Now.ToString & " for " & bb.TotalMilliseconds) Thread.Sleep(bb.TotalMilliseconds) Console.WriteLine("Woke up at " & Now.ToString(format)) End Sub 
  • Java Animate JLabel
  • java: запустить функцию через определенное количество секунд
  • Как установить таймер в Java?
  • Как создать таймер пакетного файла для выполнения / вызова другой партии в течение дня
  • Счетчик jQuery для подсчета до целевого номера
  • Windows.Forms.Timer OR System.Threading.Timer
  • Лучший метод синхронизации в C?
  • Использование System.Windows.Forms.Timer.Start () / Stop () по сравнению с Enabled = true / false
  • Пауза / остановка и запуск / возобновление Java TimerTask непрерывно?
  • Таймер, события и garbage collection: я что-то упускаю?
  • Как измерить, как долго работает функция?
  • Interesting Posts
    Давайте будем гением компьютера.