Calling a method every x minutes - c#

I want to call some method on every 5 minutes. How can I do this?
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("*** calling MyMethod *** ");
Console.ReadLine();
}
private MyMethod()
{
Console.WriteLine("*** Method is executed at {0} ***", DateTime.Now);
Console.ReadLine();
}
}

var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromMinutes(5);
var timer = new System.Threading.Timer((e) =>
{
MyMethod();
}, null, startTimeSpan, periodTimeSpan);
Edit - this answer is out of date. See https://stackoverflow.com/a/70887955/426894

I based this on #asawyer's answer. He doesn't seem to get a compile error, but some of us do. Here is a version which the C# compiler in Visual Studio 2010 will accept.
var timer = new System.Threading.Timer(
e => MyMethod(),
null,
TimeSpan.Zero,
TimeSpan.FromMinutes(5));

Update .NET 6
For most use cases in dotnet 6+, you should use the PeriodicTimer:
var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
while (await timer.WaitForNextTickAsync())
{
//Business logic
}
This has several advantages, including async / await support, avoiding memory leaks from callbacks, and CancelationToken support
Further Reading
API proposal: Modern Timer API
Execute specified function every X seconds
Why there are 5 Versions of Timer Classes in .NET?
A New Modern Timer API In .NET 6 - PeriodicTimer

Start a timer in the constructor of your class.
The interval is in milliseconds so 5*60 seconds = 300 seconds = 300000 milliseconds.
static void Main(string[] args)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 300000;
timer.Elapsed += timer_Elapsed;
timer.Start();
}
Then call GetData() in the timer_Elapsed event like this:
static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//YourCode
}

Example of using a Timer:
using System;
using System.Timers;
static void Main(string[] args)
{
Timer t = new Timer(TimeSpan.FromMinutes(5).TotalMilliseconds); // Set the time (5 mins in this case)
t.AutoReset = true;
t.Elapsed += new System.Timers.ElapsedEventHandler(your_method);
t.Start();
}
// This method is called every 5 mins
private static void your_method(object sender, ElapsedEventArgs e)
{
Console.WriteLine("...");
}

I've uploaded a Nuget Package that can make it so simple, you can have it from here ActionScheduler
It supports .NET Standard 2.0
And here how to start using it
using ActionScheduler;
var jobScheduler = new JobScheduler(TimeSpan.FromMinutes(8), new Action(() => {
//What you want to execute
}));
jobScheduler.Start(); // To Start up the Scheduler
jobScheduler.Stop(); // To Stop Scheduler from Running.

Use a Timer. Timer documentation.

Using a DispatcherTimer:
var _activeTimer = new DispatcherTimer {
Interval = TimeSpan.FromMinutes(5)
};
_activeTimer.Tick += delegate (object sender, EventArgs e) {
YourMethod();
};
_activeTimer.Start();

If you need more complicated time executions such as linux cron, you can use NCrontab.
I use NCrontab in production for long time and it works perfect!
Nuget
How to use:
* * * * *
- - - - -
| | | | |
| | | | +----- day of week (0 - 6) (Sunday=0)
| | | +------- month (1 - 12)
| | +--------- day of month (1 - 31)
| +----------- hour (0 - 23)
+------------- min (0 - 59)
using NCrontab;
//...
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// run every 5 minutes
var schedule = CrontabSchedule.Parse("*/5 * * * *");
var nextRun = schedule.GetNextOccurrence(DateTime.Now);
logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
do
{
if (DateTime.Now > nextRun)
{
logger.LogInformation("Sending notifications at: {time}", DateTimeOffset.Now);
await DoSomethingAsync();
nextRun = schedule.GetNextOccurrence(DateTime.Now);
}
await Task.Delay(1000, stoppingToken);
} while (!stoppingToken.IsCancellationRequested);
}
Add seconds if you need:
// run every 10 secs
var schedule = CrontabSchedule.Parse("0/10 * * * * *", new CrontabSchedule.ParseOptions { IncludingSeconds = true });

It can be achieved by applying while loop and calling Thread.Sleep at the end of the loop.
while (true)
{
//Your code
Thread.Sleep(5000);
}
Make sure to include using System.Threading.

while (true)
{
Thread.Sleep(60 * 5 * 1000);
Console.WriteLine("*** calling MyMethod *** ");
MyMethod();
}

Related

Launch a program every 12 hours

I want to launch a method in a program every 12 hours.
What do I have to do ?
Do I have to use a Timer to doing this ?
I have this code :
aTimer = new System.Timers.Timer(1000); //One second, (use less to add precision, use more to consume less processor time
int lastHour = DateTime.Now.Hour;
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Start();
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
if(lastHour < DateTime.Now.Hour || (lastHour == 23 && DateTime.Now.Hour == 0))
{
lastHour = DateTime.Now.Hour;
YourImportantMethod(); // Call The method with your important staff..
}
}
Can I adapt it to launch my program every 12 hours ?
A simple solution with async/await:
private static async void RepeatedAction()
{
TimeSpan delay = TimeSpan.FromHours(12);
while (true)
{
await Task.Delay(delay);
YourImportantMethod();
}
}
Use System.Threading.Timer
var start = TimeSpan.Zero;
var period = TimeSpan.FromHours(12);
var timer = new System.Threading.Timer((e) =>
{
YourImportantMethod();
}, null, start, period);
You can use Cron Jobs for this situation
Here is url check and implement. In corn job you can set when your program run

How to run a function every minute comparing old number to new number?

I'd like to run a function every minute to achieve the following:
Run function every minute
Run MySQL command to get count
Store the count into a variable
Compare the result to old result every minute
Create an If statement if number is not same to previous number.
Here is what I have:
private void Method()
{
int count = int.MinValue;
int prev_count = int.MinValue;
while (true)
{
//Get count from MySQL table
using (var conn = new MySqlConnection(ConnectionString.ConnString))
{
conn.Open();
using (var cmd = new MySqlCommand("select count(*) from table;", conn))
{
count = (int)cmd.ExecuteNonQuery();
}
}
if (count != prev_count)
{
prev_count = count;
}
}
}
My question is - is the correct way of coding this to compare the old number to new number? and also, how can I make this function run every minute?
Here how to call an event hendeler to track each given time.
Hope this will help you.
private static System.Timers.Timer timer;
private static void YourFunction(object sender, EventArgs e)
{
timer.Stop();
Console.WriteLine("Hello World!");
timer.Start();
}
static void Main(string[] args)
{
timer = new System.Timers.Timer();
timer.Interval = 5000; // time to configure
timer.Elapsed += new System.Timers.ElapsedEventHandler(YourFunction);
timer.Enabled = true;
timer.Start();
Console.ReadKey();
}

How can i run do while for specific time period c#

I have below code which will run for infinite time period but I'm going to take time as input from user.
So if user enter 15mits I want to run this code for 15 mits.
Yes I can compare the DateTime.Now with 15mits but is there any other efficient way to do so ? As this will be my multi threading application.
private static async void SendDeviceToCloudMessagesAsync(string deviceid , string deviceKey)
{
deviceClient = DeviceClient.Create("HOSTNAME", new DeviceAuthenticationWithRegistrySymmetricKey(deviceid, deviceKey), Microsoft.Azure.Devices.Client.TransportType.Mqtt);
double minTemperature = 20;
double minHumidity = 60;
int messageId = 1;
Random rand = new Random();
do
{
double currentTemperature = minTemperature + rand.NextDouble() * 15;
double currentHumidity = minHumidity + rand.NextDouble() * 20;
var telemetryDataPoint = new
{
messageId = messageId++,
deviceId = deviceid,
temperature = currentTemperature,
humidity = currentHumidity
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
var message = new Microsoft.Azure.Devices.Client.Message(Encoding.ASCII.GetBytes(messageString));
message.Properties.Add("temperatureAlert", (currentTemperature > 30) ? "true" : "false");
await deviceClient.SendEventAsync(message);
Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
await Task.Delay(1000);
} while (true);
}
You could check out System.Timers.Timer. You create an instance of it setting the interval in the constructor, then write a method to handle the Elapsed event.
// Create a timer with a two second interval.
var aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent // Name this whatever you want and put code here;
aTimer.AutoReset = true;
aTimer.Enabled = true;
All you have to do now is write the Elapsed event handler... OnTimedEvent in this case. Note that this method must have this signature:
private static void Object source, ElapsedEventArgs e)
try to replace your code against
await Task.Delay(TimeSpan.FromSeconds(1000));

C# Delay - delay in outputting to console while execution of program continues

I'm trying to find a way of causing the program to not pause but for their to be a delay to execute certain tasks. I.e. I am trying to delay outputting 'Hello' to the console for 10 seconds for example, but the program will continue to execute the rest of the program.
Using TPL:
static void Main(string[] args)
{
Console.WriteLine("Starting at " + DateTime.Now.ToString());
Task.Run(() =>
{
Thread.Sleep(10000);
Console.WriteLine("Done sleeping " + DateTime.Now.ToString());
});
Console.WriteLine("Press any Key...");
Console.ReadKey();
}
output:
Starting at 2/14/2017 3:05:09 PM
Press any Key...
Done sleeping 2/14/2017 3:05:19 PM
just note that if you press a key before 10 seconds, it will exit.
There are 2 typical ways to simulate a delay:
an asynchronous task-like: Task.Delay
or a blocking activity: Thread.Sleep
You seem to refer to the first situation.
Here it is an example
public static void Main(string[] args)
{
Both();
}
static void Both() {
var list = new Task [2];
list[0] = PauseAndWrite();
list[1] = WriteMore();
Task.WaitAll(list);
}
static async Task PauseAndWrite() {
await Task.Delay(2000);
Console.WriteLine("A !");
}
static async Task WriteMore() {
for(int i = 0; i<5; i++) {
await Task.Delay(500);
Console.WriteLine("B - " + i);
}
}
Output
B - 0
B - 1
B - 2
A !
B - 3
B - 4
Start a new thread:
Task.Factory.StartNew(new Action(() =>
{
Thread.Sleep(1000 * 10); // sleep for 10 seconds
Console.Write("Whatever");
}));
You could use a combination of Task.Delay and ContinueWith methods:
Task.Delay(10000).ContinueWith(_ => Console.WriteLine("Done"));
You could use 'Thread.Sleep(10000);'
See:
https://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.110).aspx

Timer to exact time by seconds

I'm trying to run an infinite loop in parallel with the other code, that is executed once a specific time acheived by SECOND.
In the below code I'm trying to touch the exact midnight time, that is: 00 hh: 00 mm: 00 sec
using System; // for Date/Time
using System.Threading.Tasks; // for Parallel
public class Program
{
public static void Main(string[] args)
{
Parallel.Invoke(
() =>
{
Console.WriteLine("Begin first task...");
}, // close first Action
async () =>
{
Console.WriteLine("Begin second task...");
var midNight = "00:00:00";
while (true)
{
TimeSpan duration = DateTime.Parse(midNight).Subtract(DateTime.Now);
Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds",
duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);
if(duration.Days >= 1)
await Task.Delay(8640000);
else if(duration.Hours >= 1)
await Task.Delay(360000);
else if(duration.Minutes >= 1)
await Task.Delay(60000);
else
await Task.Delay(1000);
if(duration == TimeSpan.Zero) {
Console.WriteLine("It is time... midnight is {0}", DateTime.Now);
} // close second Action `the async task`
) // end of Parallel.Invoke
} // End of Main
} // End of Program
I was able to the await statement work correctly to reach the required point, but the lock the condition if(duration == TimeSpan.Zero) never become true
First of all your program can't work as you showed because your TimeSpan duration = DateTime.Parse(midNight).Subtract(DateTime.Now); never will be positive. Second you main function will return almost immediately. Anyway you can try my solution for your problem:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main(string[] args)
{
Parallel.Invoke(
() =>{Console.WriteLine("Begin first task...");},
async () =>
{
Console.WriteLine("Begin second task...");
DateTime startDate = DateTime.Today;
while (true)
{
TimeSpan duration = DateTime.Now.Subtract(startDate);
Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds",
duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);
int delay = (int)(DateTime.Today.AddDays(1.0).Subtract(DateTime.Now).TotalMilliseconds/2);
await Task.Delay(delay>0?delay:0);
if(duration.Days >= 1)
{
Console.WriteLine("It is time... midnight is {0}", DateTime.Now);
startDate = DateTime.Today;
}
}
}
);
}
}
This will not provide you super precision as on normal PC you can't get it (you could use IRQ to get better accuracy but solution like that is far more complex).
Also as prof of concept link to 10s version.
At time version:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main(string[] args)
{
Parallel.Invoke(
async () =>
{
Console.WriteLine("Begin second task...");
TimeSpan eventTime = new TimeSpan(0,18,16,53,123); //set when run event (ex. 18:16:53.123)
DateTime endDate = DateTime.Today.Add(eventTime);
if(endDate<DateTime.Now) endDate = endDate.AddDays(1.0);
while (true)
{
TimeSpan duration = endDate.Subtract(DateTime.Now);
Console.WriteLine("looping at: {0:00} Days, {1:00} Hours, {2:00} Minutes, {3:00} Seconds, {4:00} Milliseconds", duration.Days, duration.Hours, duration.Minutes, duration.Seconds, duration.Milliseconds);
if(duration.TotalMilliseconds <= 0.0)
{
Console.WriteLine("It is time... {0}", DateTime.Now);
endDate = endDate.AddDays(1.0);
continue;
}
int delay = (int)(duration.TotalMilliseconds/2);
await Task.Delay(delay>0?delay:0);
}
}
);
Thread.Sleep(6000);
}
}
I was able to do it by changing the condition from:
if(duration == TimeSpan.Zero)
to:
if(duration.Days == 0 && duration.Hours == 0 && duration.Minutes == 0 && duration.Seconds == 0)
and to avoid the double occurrence of the event, i added another await level, so the new one became like:
if(duration.Days >= 1)
await Task.Delay(8640000);
else if(duration.Hours >= 1)
await Task.Delay(360000);
else if(duration.Minutes >= 1)
await Task.Delay(60000);
else if(duration.Seconds >= 1)
await Task.Delay(1000);
else
await Task.Delay(500);
I tried adding the if(duration.Milliseconds >= 1) await(1) but did not work, my output became as shown below:
The problem is that in your case, the duration is never zero, it goes from plus some milliseconds to minus some milliseconds.
What I would do: If duration is less than one second, wait for duration and then just assume it's the right time. In code:
if (duration.Days >= 1)
await Task.Delay(8640000);
else if (duration.Hours >= 1)
await Task.Delay(360000);
else if (duration.Minutes >= 1)
await Task.Delay(60000);
else if (duration.Seconds >= 1)
await Task.Delay(1000);
else
{
// defensive check in case duration is already negative
// this should not normally happen, but is still possible
if (duration > TimeSpan.Zero)
await Task.Delay(duration);
Console.WriteLine("It is time... midnight is {0}", DateTime.Now);
}
This won't give you millisecond accuracy, but it should be the right second, under normal circumstances.

Categories