How to use the .NET Timer class to trigger an event at a specific time?
How about something like this, using the System.Threading.Timer
class?
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);
Note that if you use a System.Threading.Timer
, the callback specified by TimerCallback
will be executed on a thread pool (non-UI) thread—so if you're planning on doing something with your UI at 4:00, you'll have to marshal the code appropriately (e.g., using Control.Invoke
in a Windows Forms app, or Dispatcher.Invoke
in a WPF app).
C# How can I trigger an event at a specific time of day?
Think out of the box.
No need for coding on this kind of job - use Scheduled Tasks, they have been in windows for a long time. You can kick off your program from this.
Update: (following update to question)
If you need to trigger a method from an already running service, use a timer and test DateTime.Now
against your target time.
How to start a timer at a specific time for a specific time?
The method below starts an initial timer with an interval based on the datetime supplied (i.e. the time entered into your textbox). When the the time is reached it starts a secondary timer that will fire every four hours from that point on.
I used System.Timers Timer rather than the Sytem.Threading Timer (because ironically the system.threading timer is not thread safe!)
public void StartTimer(DateTime time)
{
const int fourHoursInMilliseconds = 4 * 3600 * 1000;
var fourHourTimer = new Timer() {Interval = fourHoursInMilliseconds};
fourHourTimer.Elapsed += (sender, e) =>
{
//code to handle the elapsed event here
};
var span = time - DateTime.Now;
var timer = new Timer {Interval = span.TotalMilliseconds, AutoReset = false};
timer.Elapsed += (sender, e) => { fourHourTimer.Start();};
timer.Start();
}
Hope this is what you need.
How to periodically trigger an time-lapse event every specific time interval
Have UpdateEvent
set the timer interval after an event:
private void UpdateEvent()
{
if (EventIndex.Equals(1))
{
timer1.Interval = //delay until event B;
}
else
{
timer1.Interval = //delay until event A;
}
}
How to set timer to execute at specific time in c#
What you should do is write your program that does whatever you need it to do, and then use your OS's built-in task scheduler to fire it off. That'd be the most reliable. Windows's Task Scheduler, for instance, can start your app before the user logs in, handle restarting the app if necessary, log errors and send notifications, etc.
Otherwise, you'll have to run your app 24/7, and have it poll for the time at regular intervals.
For instance, you could change the interval every minute:
timer.Interval = 1000 * 60;
And inside your Elapsed
event, check the current time:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 0)
{
// do whatever
}
}
But this is really unreliable. Your app may crash. And dealing with DateTime's can be tricky.
C#: How to start a thread at a specific time
You can set up a timer at 16:00
. I've answered a similar question here.
That should help you for sure.
private System.Threading.Timer timer;
private void SetUpTimer(TimeSpan alertTime)
{
DateTime current = DateTime.Now;
TimeSpan timeToGo = alertTime - current.TimeOfDay;
if (timeToGo < TimeSpan.Zero)
{
return;//time already passed
}
this.timer = new System.Threading.Timer(x =>
{
this.SomeMethodRunsAt1600();
}, null, timeToGo, Timeout.InfiniteTimeSpan);
}
private void SomeMethodRunsAt1600()
{
//this runs at 16:00:00
}
Then set it up using
SetUpTimer(new TimeSpan(16, 00, 00));
Edit: Keep the reference of the Timer as it's subject to garbage collection irrespective of the Timer is active or not.
How to call a method daily, at specific time, in C#?
- Create a console app that does what you're looking for
- Use the Windows "Scheduled Tasks" functionality to have that console app executed at the time you need it to run
That's really all you need!
Update: if you want to do this inside your app, you have several options:
- in a Windows Forms app, you could tap into the
Application.Idle
event and check to see whether you've reached the time in the day to call your method. This method is only called when your app isn't busy with other stuff. A quick check to see if your target time has been reached shouldn't put too much stress on your app, I think... - in a ASP.NET web app, there are methods to "simulate" sending out scheduled events - check out this CodeProject article
- and of course, you can also just simply "roll your own" in any .NET app - check out this CodeProject article for a sample implementation
Update #2: if you want to check every 60 minutes, you could create a timer that wakes up every 60 minutes and if the time is up, it calls the method.
Something like this:
using System.Timers;
const double interval60Minutes = 60 * 60 * 1000; // milliseconds to one hour
Timer checkForTime = new Timer(interval60Minutes);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
and then in your event handler:
void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
if (timeIsReady())
{
SendEmail();
}
}
How to trigger .NET Core 3.1 Hosted Service at certain time?
By using the Timer method, you could run the task at a specific time, calculate the timespan between the current and target time and pass it as the dueTime parameter.
code as below:
public Task StartAsync(CancellationToken cancellationToken)
{
//DateTime.Today: 00:00:00
TimeSpan delayTime = DateTime.Today.AddHours(21) - DateTime.Now;
TimeSpan intervalTime = TimeSpan.FromMinutes(1); //86400000s == 1 day
_timer = new Timer(DoWork, null, delayTime, intervalTime);
return Task.CompletedTask;
}
Besides, the timer or Task.Delay() methods are more applied to executing a method at specified intervals, if you want to implement scheduled tasks, I suggest you could also try to use the Cronos package and the Cron Expressions to configure the scheduled task (reference: link).
The Cronos package is a lightweight but full-fledged library for parsing cron expressions and calculating next occurrences with time zones and daylight saving time in mind. The Cronos is an open source project sponsored by HangfireIO, and you can read detailed documentation from its GitHub repository.
The details steps as below:
Install the Cronos package via NuGet.
Create a CronJobService service with the following code:
public abstract class CronJobService : IHostedService, IDisposable
{
private System.Timers.Timer _timer;
private readonly CronExpression _expression;
private readonly TimeZoneInfo _timeZoneInfo;
protected CronJobService(string cronExpression, TimeZoneInfo timeZoneInfo)
{
_expression = CronExpression.Parse(cronExpression);
_timeZoneInfo = timeZoneInfo;
}
public virtual async Task StartAsync(CancellationToken cancellationToken)
{
await ScheduleJob(cancellationToken);
}
protected virtual async Task ScheduleJob(CancellationToken cancellationToken)
{
var next = _expression.GetNextOccurrence(DateTimeOffset.Now, _timeZoneInfo);
if (next.HasValue)
{
var delay = next.Value - DateTimeOffset.Now;
if (delay.TotalMilliseconds <= 0) // prevent non-positive values from being passed into Timer
{
await ScheduleJob(cancellationToken);
}
_timer = new System.Timers.Timer(delay.TotalMilliseconds);
_timer.Elapsed += async (sender, args) =>
{
_timer.Dispose(); // reset and dispose timer
_timer = null;
if (!cancellationToken.IsCancellationRequested)
{
await DoWork(cancellationToken);
}
if (!cancellationToken.IsCancellationRequested)
{
await ScheduleJob(cancellationToken); // reschedule next
}
};
_timer.Start();
}
await Task.CompletedTask;
}
public virtual async Task DoWork(CancellationToken cancellationToken)
{
await Task.Delay(5000, cancellationToken); // do the work
}
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Stop();
await Task.CompletedTask;
}
public virtual void Dispose()
{
_timer?.Dispose();
}
}
public interface IScheduleConfig<T>
{
string CronExpression { get; set; }
TimeZoneInfo TimeZoneInfo { get; set; }
}
public class ScheduleConfig<T> : IScheduleConfig<T>
{
public string CronExpression { get; set; }
public TimeZoneInfo TimeZoneInfo { get; set; }
}
public static class ScheduledServiceExtensions
{
public static IServiceCollection AddCronJob<T>(this IServiceCollection services, Action<IScheduleConfig<T>> options) where T : CronJobService
{
if (options == null)
{
throw new ArgumentNullException(nameof(options), @"Please provide Schedule Configurations.");
}
var config = new ScheduleConfig<T>();
options.Invoke(config);
if (string.IsNullOrWhiteSpace(config.CronExpression))
{
throw new ArgumentNullException(nameof(ScheduleConfig<T>.CronExpression), @"Empty Cron Expression is not allowed.");
}
services.AddSingleton<IScheduleConfig<T>>(config);
services.AddHostedService<T>();
return services;
}
}create a ScheduleJob.cs:
public class ScheduleJob: CronJobService
{
private readonly ILogger<ScheduleJob> _logger;
public ScheduleJob(IScheduleConfig<ScheduleJob> config, ILogger<ScheduleJob> logger)
: base(config.CronExpression, config.TimeZoneInfo)
{
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob starts.");
return base.StartAsync(cancellationToken);
}
public override Task DoWork(CancellationToken cancellationToken)
{
_logger.LogInformation($"{DateTime.Now:hh:mm:ss} ScheduleJob is working.");
return Task.CompletedTask;
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob is stopping.");
return base.StopAsync(cancellationToken);
}
}Register the ScheduleJob service in the ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<HelloWorldHostedService>();
services.AddCronJob<ScheduleJob>(c=>
{
c.TimeZoneInfo = TimeZoneInfo.Local;
c.CronExpression = @"25 21 * * *"; // 21:25 PM daily.
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}Then the result as below:
Need A Timer To Fire At Specific Time And Every 5 Minutes Until Job Complete
Here's a basic framework you can start from:
Public Class Form1
Private Enum MaintenanceState
WaitingToStart
Started
End Enum
Private Target As DateTime
Private state As MaintenanceState = MaintenanceState.WaitingToStart
Private MaintenanceTime As New TimeSpan(4, 0, 0) ' 4:00 am
Private WaitingInterval As New TimeSpan(0, 5, 0) ' Five minutes
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Target = GetNextMaintenanceTarget(MaintenanceTime)
tmr_Maintenance.Interval = 1000
tmr_Maintenance.Start()
End Sub
Private Sub tmr_Maintenance_Tick(sender As Object, e As EventArgs) Handles tmr_Maintenance.Tick
' optionally display time remaining until next target
Dim ts As TimeSpan = Target.Subtract(DateTime.Now)
Label1.Text = ts.ToString("hh\:mm\:ss")
' see if we've hit the target
If DateTime.Now >= Target Then
tmr_Maintenance.Stop()
Select Case state
Case MaintenanceState.WaitingToStart
' ... start all the jobs ...
state = MaintenanceState.Started
Target = DateTime.Now.Add(WaitingInterval)
Case MaintenanceState.Started
' ... check to see if the jobs are all done ...
If Not AllJobsCompleted Then
Target = DateTime.Now.Add(WaitingInterval)
Else
state = MaintenanceState.WaitingToStart
Target = GetNextMaintenanceTarget(MaintenanceTime)
End If
End Select
tmr_Maintenance.Start()
End If
End Sub
Private Function GetNextMaintenanceTarget(ByVal time As TimeSpan) As DateTime
Dim dt As DateTime = DateTime.Today.Add(time)
If DateTime.Now > dt Then
dt = dt.AddDays(1) ' already past target time for today, next start is tomorrow
End If
Return dt
End Function
End Class
Related Topics
How to Compile and Run C# Program Without Using Visual Studio
Why Do We Need the "Event" Keyword While Defining Events
Suppress Null Value Types from Being Emitted by Xmlserializer
Ms Chart Rectangular Annotation Width in Percent and Not Pixel
Installing Windows Service Programmatically
How to Maximize the Browser Window in Selenium Webdriver (Selenium 2) Using C#
The Bare Minimum Needed to Write a Msmq Sample Application
How to Use System.Net.Httpclient to Post a Complex Type
How to Get the Last Four Characters from a String in C#
Why Is a Round-Trip Conversion via a String Not Safe for a Double
How to Create Custom Http Status Codes
Differencebetween Iequalitycomparer<T> and Iequatable<T>
How to Create a File and Any Folders, If the Folders Don't Exist
Windows 7 Progress Bar in Taskbar in C#
Is There a Faster Way Than This to Find All the Files in a Directory and All Sub Directories