how to run code depending on the time - c#

I have a little problem. I didn't find a suitable title, sorry
I have a time column at my database and I want to do something (not important) whenever currenttime==timeValueAtMyDatabase. How?
if(currenttime==timeValueAtMyDatabase)
{
//do something
}

If you are okay with the code executing in a different thread and you can use whatever libraries you want (Rx in this case), I personally prefer this method:
Observable.Timer(timeToDoTheThing).Subscribe(codeToRun);
timeToDoTheThing is the time that the code should be executed at and codeToRun is the code that will run when the time is reached (in the form of a void returning delegate that takes one long parameter).
Some things to note:
The event will occur immediately if the time provided is in the past.
The event will execute in a background thread. You can control which thread it runs in by providing a scheduler, but that is a bit more complex and I prefer to just make my code thread safe rather than trying to control which threads execute which blocks of code.
Below is a complete program that will exemplify this. You will need to install the Rx-Main NuGet package to the project for it to work and build against .NET 4+.
using System;
using System.Reactive.Linq;
using System.Threading;
namespace Test
{
public class Class
{
public static void Main()
{
var timeToDoTheThing = new DateTimeOffset(2013, 10, 19, 22, 19, 30, TimeSpan.Zero);
Action<long> codeToRun = _ => Console.WriteLine("It is time.");
Observable.Timer(timeToDoTheThing).Subscribe(codeToRun);
Thread.Sleep(100000);
}
}
}

If this is a Windows Forms Application, you can use a timer and check whether some of the entries are less then DateTime.Now.
If it is a web application, you can use a cron job. Check out the following link: Creating Cron Jobs in C#.

Use a timer control that ticks on appropriate intervals.
On ever tick compare the current time with the time in your database.
You will need to account for differences. For example if it ticks at 0.1sec, 1.1sec, 2.1sec and the time in your database is 1sec.
You'll have to find an appropriate way to account for such differences.

Related

Why Timer has no properties, how to get it's interval after initialization?

I'm using a System.Threading.Timer in my windows service for nightly import routines. It looks every minute into the database for new files to be imported. Now, since the service runs all day long, i want to change it so that it runs at night every minute and at day every 5th minute.
Therefore i thought i could check the current time, between 7am and 10PM use the day-interval-configuration value, otherwise the night-interval.
Now to the actual question: why is there no property in the Timer-class which indicates the current period/interval? Then i could decide whether i have to change it or not according to it's value.
As a workaround i could store it in an additonal field, but i wonder if it's possible to get the value from the timer itself.
Note that i'm using this constructor:
//start immediately, interval is in TimeSpan, default is every minute
importTimer = new System.Threading.Timer(
ImportTimer_Elapsed,
null,
TimeSpan.Zero,
Settings.Default.ServiceInterval_Night
);
Why is there no property in the Timer-class which indicates the current period/interval?
I assume (I'm not part of the .NET implementation team, so have to assume) this is because it used a Win32 Waitable Timer. And there is no API to get the settings of a Waitable Timer.
Note, if such properties did exit there would be a race condition:
Thread 1 reads the property and starts some business logic based on it
Thread 2 changes the property (invalidating thread 1's logic)
Thread 1 updates the property.
while any specific use of a timer may not suffer this, the general case has to cater for it.
(In Win32 this is even worse a WaitableTimer can be named, and thus accessed from other processes.)
You can use System.Timers.Timer instead, which provides such a property (".Intervall")
System.Threading.Timer does not have an internal field with the intervall value. I took a look into the .net code and i saw it isnt possible to get the current period by reflection.
Don't mess around with the tick rate. Instead invoke your code after a fixed number of ticks, depending on time:
private void ImportTimer_Elapsed(object o)
{
tickCount--;
if (tickCount <= 0)
{
// do your stuff
tickCount = Between7AMAnd10PM() ? 5 : 1;
}
}

Asp.net -- Multithreading in C#

I have a huge data to run which takes awful amount of time so thought Threading might do the job for me quickly.
What I do : Call SQL Stored Procedures from ASP.NET front end and processing takes place there and it takes almost 30 hours.
What I need : I have split the data into different batches and created respective SPs for each. Now I require all SPs to be running at the same time at a single button click.
Please help!
I used the below code but it doesnt seem to run in parallel.
protected void Button3_Click(object sender, EventArgs e)
{
Thread t1 = new Thread(Method1);
Thread t2 = new Thread(Method2);
t1.Start();
t2.Start();
t1.Join();
t2.Join();
}
void Method1()
{
for (int i = 0; i < 10000; i++)
{
Response.Write("hello1"+i);
Response.Write("<br>");
}
}
void Method2()
{
for (int i = 0; i < 10000; i++)
{
Response.Write("hello2" + i);
}
}
You probably don't want to be doing this directly in ASP.NET for a variety of reasons, such as the worker process has limited execution time.
Also note that the SqlConnection etc also have their own time limits.
What you should really do is queue up the work to do (using IPC or another database table etc) and have something like a Windows service or external process in a scheduled task pick up and process through the queue.
Hell, you could even kick off a job within SQL Server and have that directly do the work.
Threading doesnt magically speed up your process.
If you dont know what you are doing server side threading is not a good idea in general.
Sql server probably will time out for 30hrs :)
for 30 hours of job Asp.net is not the way to go. This is a big process and you shouldn't handle it within Asp.net. As an alternative you might want to write a windows service. Pass your parameters to it ( maybe with msmq or some kind of messaging system) Do your process and send progress to web application show it with signalR or ajax pulls.
Narendran, start here:
http://www.albahari.com/threading/
This is the best Threading tutorial I have seen online and respective book is also very good.
Make sure you spend enough time to go through the whole tutorial(I have done it and believe me, it worth it!).
As said above using Join method of thread class in this case defeats the purpose of using threads. Instead of using join use lock(see basic Synchoronization in the above tutorial) to make sure threads are synchronized.
Also as mentioned, before doing multithreading Run those stored procedures on SQL server directly and all together. If it still takes 30 hours for them to get executed ,then using Threading won't do any help. If you see less than 30 hours then you may benefeat from multithreading.

How to trigger a timer tick programmatically?

Let's say I have a Windows Forms timer configured with a 10 second (10k ms) interval:
myTimer.Interval = 10000;
I want to start it and fire off the Tick event right away:
myTimer.Start();
myTimer_Tick(null, null);
The last line works but is there a better or more appropriate way?
The only thing I'd do differently is to move the actual Tick functionality into a separate method, so that you don't have to call the event directly.
myTimer.Start();
ProcessTick();
private void MyTimer_Tick(...)
{
ProcessTick();
}
private void ProcessTick()
{
...
}
Primarily, I'd do this as direct calling of events seems to me to be a Code Smell - often it indicates spagetti structure code.
There are at least 4 different "Timers" in .NET. Using System.Threading you can get one that specifically allows you to set the initial delay.
var Timer = new Timer(Timer_Elapsed, null, 0, 10000);
There are benefits to using the different timers and here is a good article discussing them all.
You could set the interval to 1 (0 probably means infinite timeout) and set it to 10k when it ticks for the first time.
The timer will tick "very soon" (depending what type of Timer you are using, see this) but the execution will not continue with the click handler as in your solution.
(I suppose you knew about the solution from Bevan).
Use two timers.
The First that has the normal interval you want to use and just enables the Second timer.
The Second timer has an interval of 100ms and is normally disabled. It runs your code and then disables itself.
To manually trigger, just enabled the Second timer.
This also allows you to trigger the code from another form using full qualification naming to the Second timer. I use this when calling from one form to another.

Callback with a time

I want to implement a method that callback a method at a precise time. We can have more than a method that can be called at the same time.
public void CallmeBack(DateTime time, Action callback)
{
}
What's the best implementation in C# ?
My quick and dirty solution was to create a dictionary Dictionary<DateTime, List<Action>> and to make a timer every each (minute/second) and check the time (DateTime.Now) and a current time in the test mode.
The solution have to be "Safe" if the current machine time changed. So a simple solution like this couldn't work :
Timer timer = new Timer((param) => {callback.Invoke();}, null,
(long)(time - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
Edit :
Typical case where simple timer don't work is DST and manual time/date adjustment.
Plus, I just want the callback executed once not multiple times.
What you are looking for is a cron library. There are many out there. Some have a lot of features and are a bit heavy. Here is a blog post about cron jobs and a library that I have used in production code.
http://blog.bobcravens.com/2009/10/an-event-based-cron-scheduled-job-in-c/
Hope that helps get you started.
Bob
A couple of alternatives you may want to consider:
You could use a task scheduler such as :http://taskscheduler.codeplex.com/
You could stick with a timer and listen for time changes using: SystemEvents.TimeChanged. That event is triggered by user time changes. I assume you can handle predictable time changes (daylight saving etc.) when setting the timer in the first place. I'm not sure about NTP-related changes - you'd need to investigate that further.

C# - Alternative to System.Timers.Timer, to call a function at a specific time

I want to call a specific function on my C# application at a specific time. At first I thought about using a Timer (System.Time.Timer), but that soon became impossible to use. Why?
Simple. The Timer class requires a Interval in milliseconds, but considering that I might want the function to be executed, let's says in a week that would mean:
7 days = 168 hours;
168 hours = 10,080 minutes;
10,080 minutes = 604,800 seconds;
604,800 seconds = 604,800,000 milliseconds;
So the interval would be 604,800,000;
Now let's remember that the Interval accepted data type is int, and as we know int range goes from -2,147,483,648 to 2,147,483,647.
That makes Timer useless, not in this case, but in the case of more than about 25 days, once we cannot set a Interval bigger that 2,147,483,647 milliseconds.
So I need a solution where I could specify when the function should be called. Something like this:
solution.ExecuteAt = "30-04-2010 15:10:00";
solution.Function = "functionName";
solution.Start();
So when the System Time would reach "30-04-2010 15:10:00" the function would be executed in the application.
How can this problem be solved?
Additional information: What will these functions do?
Getting climate information and based on that information:
Starting / Shutting down other applications (most of them console based);
Sending custom commands to those console applications;
Power down, rebooting, sleep, hibernate the computer;
And if possible schedule the BIOS to power up the computer;
EDIT:
It would seem that the Interval accepted data type is double, however if you set a value bigger that an int to the Interval, and call Start() it throws a exception [0, Int32.MaxValue].
EDIT 2:
Jørn Schou-Rode suggested using Ncron to handle the scheduling tasks, and at first look this seems a good solution, but I would like to hear about some who has worked with it.
Your "Start()" method should spawn a thread that wakes up at a defined interval, checks the time, and if you haven't reached the desired time, goes back to sleep.
I would recommend that you just write a program that deals with the business part of it and then execute that program when necessary by using Windows Task Scheduler.
One approach to task scheduling, simliar to that proposed by klausbyskov, is to built your scheduling service on top of an existing .NET scheduling framework/library. Compared to using the Windows Task Scheduler, this has the advantages of (a) allowing several jobs to be defined in the same project and (b) keeping jobs and scheduling logic "together" - i.e. not relying on server settings prone to get lost in system upgrades/replacements.
I know of two open-source projects that offer this kind of functionality:
"Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems." I have never actually used this framework myself, but from studying the website, I have the impression of a very solid tool, providing many cool features. The fact that there [quartz-net] tag on Stackoverflow might also indicate that it is actually used in the wild.
"NCron is a light-weight library for building and deploying scheduled background jobs on the .NET server platform." It does not have half as many features as Quartz.NET, and it does not have any tag on Stackoverflow, but the author (yours truly) believes that its low-friction API makes it somewhat easier to get started with.
Building your scheduling service on top of NCron, you can schedule a CleanupJob for weekly execution using a single line of code:
service.Weekly().Run<CleanupJob>();
Ok, you will need around three lines of boiler plate code on top of that to actually turn your project into a Windows service, but it sounds more impressive when I claim that it can be done with one line of code ;)
You could write some sort of wrapper class for a Timer which takes a DateTime instance. Then you perform the following steps:
Determine the difference between DateTime.Now and the desired time.
If the difference (in milliseconds) is larger than the maximum allowed value for the Timer.Interval property, set the Interval to the maximum allowed value (i.e. double.MaxValue or whatever) and start it.
Now, when the timer elapses the first time, you simply go back to step 1.
At some time, the difference will be smaller than the maximum allowed value for the Interval property, and then you could fire an event in your wrapper which ultimately calls the desired method.
Use the System.Threading.Timer:
var timer = new System.Threading.Timer(delegate { }, // Pass here a delegate to the method
null,
TimeSpan.FromDays(7), // Execute Method after 7 days.
TimeSpan.Zero);
You can use the System.Threading.Timer class, which provides a constructor accepting an interval expressed as an Int64, which should be enough for your needs.
Now for the other stuff :
You can start/stop/configure program using the Process class (I don't really get what you call "custom commands")
You cannot restart or shut down or control the local BIOS using native .NET classes. Rebooting / restarting is possible through Interop (calling native Windows API from .NET), and scheduling the BIOS is just impossible. Or maybe with a special server motherboard ? I don't know..
The class System.Threading.Timer has the same limitation too (it would throw an ArgumentOutOfRangeException according to MSDN).
There seems to be no .Net Framework class natively adept to circumvent the Int32.MaxValue milliseconds upper bound.
public static class Scheduler
{
private const long TimerGranularity = 100;
static Scheduler()
{
ScheduleTimer = new Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
Tasks = new SortedQueue<Task>();
}
private static void Callback(object state)
{
var first = Tasks.Peek();
if(first.ExecuteAt<DateTime.Now)
{
Tasks.Dequeue();
var executionThread = new Thread(() => first.Function());
executionThread.Start();
}
}
private static Timer ScheduleTimer { get; set; }
public static void Start()
{
ScheduleTimer.Change(0, TimerGranularity);
}
public static void Add(Task task)
{
Tasks.Enqueue(task);
}
public static SortedQueue<Task> Tasks { get; set; }
}
public class Task : IComparable<Task>
{
public Func<Boolean> Function { get; set; }
public DateTime ExecuteAt { get; set; }
public int CompareTo(Task other)
{
return ExecuteAt.CompareTo(other.ExecuteAt);
}
}
The solution I'd use is something similar to the above example: a class Scheduler that manages all the Tasks (in order to avoid having a timer for each task we are going to schedule).
Tasks are added to the a queue able to perform sorted insertion. Note that SortedQueue<T> is not a type of the .Net Framework but an hypothetical, easy-to-code collection capable of sorted insertion on a comparable type T.
The scheduler awakes every TimerGranularity milliseconds and checks for the first task whose `ExecuteAt' time has been surpassed; then executes it on a separate thread.
Additional effort could be done by creating a list of all surpassed tasks (instead of the first one only); but I left it out for the sake of clarity.
There is exist exist nu-get called Quartz.NET.
You can use it exactly for this.

Categories