Best way to run a background task with timer - c#

The following code run a task which check, each 5 seconds, the status of a database. I had to use the BeginInvoke but I'm not sure is the best way to do:
public btnDatabaseStatus()
{
InitializeComponent();
if (!DesignerProperties.GetIsInDesignMode(this))
Global.LM.SetTraduzioniWindow(this);
Init();
DispatcherOperation dbStatDispatcher = null;
try
{
dbStatDispatcher = App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
Timer timer = new Timer(5000);
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}));
}
catch (Exception ex)
{
if (dbStatDispatcher != null) dbStatDispatcher.Abort();
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
if (App.Current!=null) App.Current.Dispatcher.BeginInvoke(new Action(() => { IsDbConnected = Dbs[0].IsConnected; }));
}
private void Init()
{
Dbs = null;
Dbs = Global.DBM.DB.Values.Where(d => d.IsExternalDB).ToList();
lstvDatabase.ItemsSource = Dbs;
}
I'm afraid concerning the closing of main application as sometimes the Dispatcher is null. Any hints to improve the code?

Forget about Dispatcher.BeginInvoke and System.Threading.Timer.
Use a WPF DispatcherTimer:
public btnDatabaseStatus()
{
InitializeComponent();
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
timer.Tick += OnTimerTick;
timer.Start();
}
private void OnTimerTick(object sender, EventArgs e)
{
IsDbConnected = Dbs[0].IsConnected;
}
Or shorter:
public btnDatabaseStatus()
{
InitializeComponent();
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
timer.Tick += (s, e) => IsDbConnected = Dbs[0].IsConnected;
timer.Start();
}
If the Tick handler is supposed to do some long-running task, you may declare it async:
private async void OnTimerTick(object sender, EventArgs e)
{
await SomeLongRunningMethod();
// probably update UI after await
}

Related

WPF non blocking UI Popup

In an Office Add-In I need to call a WPF which executes a function which may timeout but I want the UI to be responsive to allow the user to click the cancel/close button.
So far my code is the following:
// From the Ribbon
var f = new Forms.CheckConnectivityPopup();
f.doneEvent.WaitOne();
// Get the status from the popup or null if the operation was cancelled
var status = f.status;
if(status != null)
// Continue the execution
--------------------------------
public partial class CheckConnectivityPopup : MetroWindow
{
public readonly BackgroundWorker worker = new BackgroundWorker();
public AutoResetEvent doneEvent = new AutoResetEvent(false);
public Status status = null;
public CheckConnectivityPopup()
{
InitializeComponent();
this.Show();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// displayAndCheck();
status = CheckStatus();
Thread.Sleep(10000); // to simulate the time
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
doneEvent.Set();
this.Close();
}
}
So far the popup is frozen until sleep period is completed.
WaitOne() blocks the current thread. You could replace the AutoResetEvent with a SemaphoreSlim:
public partial class CheckConnectivityPopup : MetroWindow
{
public readonly BackgroundWorker worker = new BackgroundWorker();
public SemaphoreSlim doneEvent = new SemaphoreSlim(0, 1);
public Status status = null;
public CheckConnectivityPopup()
{
InitializeComponent();
this.Show();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
//displayAndCheck();
status = CheckStatus();
Thread.Sleep(10000); // to simulate the time
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
doneEvent.Release();
this.Close();
}
}
...that you can await asynchronously:
var f = new Forms.CheckConnectivityPopup();
await f.doneEvent.WaitAsync();
For you to be able to await the WaitAsync() method, you must mark the method where you create the instance of the CheckConnectivityPopup as async:
void async YourMethod() { ... }
If this is not an option for some reason, you could use the ContinueWith method instead:
var f = new Forms.CheckConnectivityPopup();
f.doneEvent.WaitAsync().ContinueWith(_ =>
{
var status = f.status;
if (status != null)
{
//...
}
});

Using BackgroundWorker to complete two methods one after the other WPF/C#

In my program I have two methods that takes a while to complete, about few minutes each. While these methods are being executed, I display a Progress Bar in a separate window which shows the progress of each method. My two methods are in a static Utility class. They look like the following:
public static class Utility
{
public static bool TimeConsumingMethodOne(object sender)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
(sender as BackgroundWorker).ReportProgress(i);
}
return true;
}
public static bool TimeConsumingMethodTwo(object sender)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(50);
(sender as BackgroundWorker).ReportProgress(i);
}
return true;
}
}
Reading through similar questions in SO I learned that I should use BackgroundWorker and used the RunWorkerCompleted() to see when the worker completes its work. So in my Main() I used BackgroundWorer() and subscribed to the RunWorkerCompleted() method. My goal here is to run the TimeConsumingMethodOne() first (and display progress while running), then once finished, run TimeConsumingMethodTwo() and show progress again, and when that's completed output the message box (which simulates some other work in my program). My Main() looks like the following:
public partial class MainWindow : Window
{
public enum MethodType
{
One,
Two
}
private BackgroundWorker worker = null;
private AutoResetEvent _resetEventOne = new AutoResetEvent(false);
private AutoResetEvent _resetEventTwo = new AutoResetEvent(false);
private ProgressBarWindow pbWindowOne = null;
private ProgressBarWindow pbWindowTwo = null;
public MainWindow()
{
InitializeComponent();
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
RunMethodCallers(sender, MethodType.One);
_resetEventOne.WaitOne();
RunMethodCallers(sender, MethodType.Two);
_resetEventTwo.WaitOne();
MessageBox.Show("COMPLETED!");
}
private void RunMethodCallers(object sender, MethodType type)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
switch (type)
{
case MethodType.One:
worker.DoWork += MethodOneCaller;
worker.ProgressChanged += worker_ProgressChangedOne;
worker.RunWorkerCompleted += worker_RunWorkerCompletedOne;
break;
case MethodType.Two:
worker.DoWork += MethodTwoCaller;
worker.ProgressChanged += worker_ProgressChangedTwo;
worker.RunWorkerCompleted += worker_RunWorkerCompletedTwo;
break;
}
worker.RunWorkerAsync();
}
private void MethodOneCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowOne = new ProgressBarWindow("Running Method One");
pbWindowOne.Owner = this;
pbWindowOne.Show();
});
Utility.TimeConsumingMethodOne(sender);
}
private void MethodTwoCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowTwo = new ProgressBarWindow("Running Method Two");
pbWindowTwo.Owner = this;
pbWindowTwo.Show();
});
Utility.TimeConsumingMethodTwo(sender);
}
private void worker_RunWorkerCompletedOne(object sender, RunWorkerCompletedEventArgs e)
{
_resetEventOne.Set();
}
private void worker_RunWorkerCompletedTwo(object sender, RunWorkerCompletedEventArgs e)
{
_resetEventTwo.Set();
}
private void worker_ProgressChangedOne(object sender, ProgressChangedEventArgs e)
{
pbWindowOne.SetProgressUpdate(e.ProgressPercentage);
}
private void worker_ProgressChangedTwo(object sender, ProgressChangedEventArgs e)
{
pbWindowTwo.SetProgressUpdate(e.ProgressPercentage);
}
}
Now the problem I have is, when I use _resetEventOne.WaitOne(); the UI hangs. If I removed those two waits, both methods run asynchronously and the execution moves on and outputs the MessageBox even before those two methods complete.
What am I doing wrong? How do I get the program to finish my first BackgroundWorker and then move onto the next, and then when that's done, output the MessageBox?
Now the problem I have is, when I use _resetEventOne.WaitOne(); the UI hangs. If I removed those two waits, both methods run asynchronously and the execution moves on and outputs the MessageBox even before those two methods complete.
What am I doing wrong?
When you call WaitOne(), you are blocking the UI thread, causing the UI to hang. If you remove that call, then of course you start both workers at once.
There are several different ways to approach your question. One is to stick as closely to your current implementation, and just fix the barest minimum to get it to work. Doing that, what you'll need to do is perform the actual next statement in the RunWorkerCompleted handler, instead of using an event to wait for the handler to execute.
That looks like this:
public partial class MainWindow : Window
{
public enum MethodType
{
One,
Two
}
private BackgroundWorker worker = null;
private ProgressBarWindow pbWindowOne = null;
private ProgressBarWindow pbWindowTwo = null;
public MainWindow()
{
InitializeComponent();
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
RunMethodCallers(sender, MethodType.One);
}
private void RunMethodCallers(object sender, MethodType type)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
switch (type)
{
case MethodType.One:
worker.DoWork += MethodOneCaller;
worker.ProgressChanged += worker_ProgressChangedOne;
worker.RunWorkerCompleted += worker_RunWorkerCompletedOne;
break;
case MethodType.Two:
worker.DoWork += MethodTwoCaller;
worker.ProgressChanged += worker_ProgressChangedTwo;
worker.RunWorkerCompleted += worker_RunWorkerCompletedTwo;
break;
}
worker.RunWorkerAsync();
}
private void MethodOneCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowOne = new ProgressBarWindow("Running Method One");
pbWindowOne.Owner = this;
pbWindowOne.Show();
});
Utility.TimeConsumingMethodOne(sender);
}
private void MethodTwoCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowTwo = new ProgressBarWindow("Running Method Two");
pbWindowTwo.Owner = this;
pbWindowTwo.Show();
});
Utility.TimeConsumingMethodTwo(sender);
}
private void worker_RunWorkerCompletedOne(object sender, RunWorkerCompletedEventArgs e)
{
RunMethodCallers(sender, MethodType.Two);
}
private void worker_RunWorkerCompletedTwo(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("COMPLETED!");
}
private void worker_ProgressChangedOne(object sender, ProgressChangedEventArgs e)
{
pbWindowOne.SetProgressUpdate(e.ProgressPercentage);
}
private void worker_ProgressChangedTwo(object sender, ProgressChangedEventArgs e)
{
pbWindowTwo.SetProgressUpdate(e.ProgressPercentage);
}
}
That said, BackgroundWorker has been made obsolete by the newer task-based API with async and await. With some small changes to your code, it can be adapted to use that newer idiom:
public partial class MainWindow : Window
{
public enum MethodType
{
One,
Two
}
private ProgressBarWindow pbWindowOne = null;
private ProgressBarWindow pbWindowTwo = null;
public MainWindow()
{
InitializeComponent();
}
private async void btnRun_Click(object sender, RoutedEventArgs e)
{
await RunMethodCallers(sender, MethodType.One);
await RunMethodCallers(sender, MethodType.Two);
MessageBox.Show("COMPLETED!");
}
private async Task RunMethodCallers(object sender, MethodType type)
{
IProgress<int> progress;
switch (type)
{
case MethodType.One:
progress = new Progress<int>(i => pbWindowOne.SetProgressUpdate(i));
await Task.Run(() => MethodOneCaller(progress));
break;
case MethodType.Two:
progress = new Progress<int>(i => pbWindowTwo.SetProgressUpdate(i));
await Task.Run(() => MethodTwoCaller(progress));
break;
}
}
private void MethodOneCaller(IProgress<int> progress)
{
Dispatcher.Invoke(() =>
{
pbWindowOne = new ProgressBarWindow("Running Method One");
pbWindowOne.Owner = this;
pbWindowOne.Show();
});
Utility.TimeConsumingMethodOne(progress);
}
private void MethodTwoCaller(IProgress<int> progress)
{
Dispatcher.Invoke(() =>
{
pbWindowTwo = new ProgressBarWindow("Running Method Two");
pbWindowTwo.Owner = this;
pbWindowTwo.Show();
});
Utility.TimeConsumingMethodTwo(progress);
}
}
To do the above does require a small adjustment to the Utility class as well:
static class Utility
{
public static bool TimeConsumingMethodOne(IProgress<int> progress)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
progress.Report(i);
}
return true;
}
public static bool TimeConsumingMethodTwo(IProgress<int> progress)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(50);
progress.Report(i);
}
return true;
}
}
That is, the Progress<T> class takes the place of the BackgroundWorker.ProgressChanged event and ReportProgress() method.
Note that with the above, the code has gotten significantly shorter, simpler, and is written in a more direct way (i.e. related statements are with each other in the same method now).
The example you gave is necessarily simplified. That's perfectly fine, but it does mean that it's not known here what the Thread.Sleep() method represents. In fact, in many cases, this sort of thing can be refactored further such that only the long-running work is done asynchronously. This can sometimes simplify the progress-reporting even further, because it can be done after await-ing each individual asynchronously-executed work component.
For example, let's suppose the work in the loop is either inherently asynchronous or is costly enough that it's reasonable to use Task.Run() to execute each loop iteration. For the purpose of the same, that can be represented using Task.Delay():
static class Utility
{
public static async Task<bool> TimeConsumingMethodOne(Action<int> progress)
{
for (int i = 1; i <= 100; i++)
{
await Task.Delay(100);
progress(i);
}
return true;
}
public static async Task<bool> TimeConsumingMethodTwo(Action<int> progress)
{
for (int i = 1; i <= 100; i++)
{
await Task.Delay(50);
progress(i);
}
return true;
}
}
In the above, I also don't use Progress<T>. Just a simple Action<int> delegate for the caller to use however they want.
And with that change, your window code gets even simpler:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void btnRun_Click(object sender, RoutedEventArgs e)
{
await MethodOneCaller();
await MethodTwoCaller();
MessageBox.Show("COMPLETED!");
}
private async Task MethodOneCaller()
{
ProgressBarWindow pbWindowOne =
new ProgressBarWindow("Running Method One") { Owner = this };
pbWindowOne.Show();
await Utility.TimeConsumingMethodOne(i => pbWindowOne.SetProgressUpdate(i));
}
private async Task MethodTwoCaller()
{
ProgressBarWindow pbWindowTwo =
new ProgressBarWindow("Running Method Two") { Owner = this };
pbWindowTwo.Show();
await Utility.TimeConsumingMethodTwo(i => pbWindowTwo.SetProgressUpdate(i));
}
}
Granted, I took the opportunity to remove the MethodType enum and just call the methods directly, which shortened the code even more. But even if all you did was avoid the use of Dispatcher.Invoke(), that still simplifies the code a lot.
In addition to all that, if you were using data binding to represent the progress state instead of setting the value directly, WPF would handle the cross-thread invocation implicitly for you, so that the Progress<T> class isn't even required even if you can't refactor the Utility class code for it itself to be async.
But, those are minor refinements compared to moving away from BackgroundWorker. I recommend doing that, but whether you invest time in those further refinements is less important.
An option i prefer is to have those 2 methods in a different thread and use a while loop to check if thread is still running and if it is use Task.Delay()
EG.
private async void BlahBahBlahAsync()
{
Thread testThread = new Thread(delegate () { });
newThread = new Thread(delegate ()
{
Timeconsuming();
});
newThread.Start();
while (testThread.IsAlive)
{
await Task.Delay(50);
}
}
private void Timeconsuming()
{
// stuff that takes a while
}

Creating a timer winform application using only delegates and events [WITHOUT TIMER OBJECT]

While using timers, stopwatches and threads is the standard way, I was wondering if there was a way to create a Winform Application in c# which had a label with initial value as 0 and which automatically kept on incrementing once a button is clicked and when the same button is clicked again it should pause. Personally, I feel that the trick is to use multicast delegates. But I am stuck as to how to proceed.
NOTE: Possible use of method callback and InvokeRequired().
this code dose not use timer or stopwatch.
i have wrote a simple class for you, forgive me if its not so standard because im so lazy for now :)
public partial class Form1 : Form
{
CancellationTokenSource src;
CancellationToken t;
public Form1()
{
InitializeComponent();
}
//start incrementing
private async void button1_Click(object sender, EventArgs e)
{
this.Start.Enabled = false;
this.Cancel.Enabled = true;
this.src = new CancellationTokenSource();
this.t = this.src.Token;
try
{
while (true)
{
var tsk = Task.Factory.StartNew<int>(() =>
{
Task.Delay(500);
var txt = int.Parse(this.Display.Text) + 1;
return (txt);
}, this.t);
var result = await tsk;
this.Display.Text = result.ToString();
}
}
catch (Exception ex)
{
return;
}
}
// Stop incrementing
private void button1_Click_1(object sender, EventArgs e)
{
this.src.Cancel();
this.Cancel.Enabled = true;
this.Start.Enabled = true;
}
}
Really not sure why you think this can be done with your restrictions in place. If you want a delay in-between your "events", then you need to use some kind of Timer, or some kind of thread (classic Thread or some kind of Task) that has a delay within it...no way around that.
Here's another approach that'll probably violate your restrictions:
public partial class Form1 : Form
{
private Int64 value = -1;
private bool Paused = true;
private int IntervalInMilliseconds = 100;
private System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);
public Form1()
{
InitializeComponent();
this.Shown += Form1_Shown;
}
private async void Form1_Shown(object sender, EventArgs e)
{
await Task.Run(delegate ()
{
while (true)
{
value++;
label1.Invoke((MethodInvoker)delegate ()
{
label1.Text = value.ToString();
});
System.Threading.Thread.Sleep(IntervalInMilliseconds);
mre.WaitOne();
}
});
}
private void button1_Click(object sender, EventArgs e)
{
if (Paused)
{
mre.Set();
}
else
{
mre.Reset();
}
Paused = !Paused;
}
}
USE an EVENT.
If you can not use timers or threads, then how about creating a do while loop that executes an event.
Some PSEUDO code is below - it should give you the idea..
bool IWantEvents = false;
public event EventHandler<myHandler> myNonTimerEvent ;
FormStart()
{
this.myNonTimerEvent += new MyNonTimerEventHandler();
IWantEvents = true;
Do
{
.. do some weird stuff - set IWantEvents False on condition ..
}
while(IWantEvents)
}
MyNonTimerEventHandler()
{
.. Do what I would do if I was using a timer event.
}

Countdown timer using System.Timers.Timer in WPF application [duplicate]

How can I implement the following in my piece of code written in WPF C#?
I have a ElementFlow control in which I have implemented a SelectionChanged event which (by definition) fires up a specific event when the control's item selection has changed.
What I would like it to do is:
Start a timer
If the timer reaches 2 seconds then launch a MessageBox saying ("Hi there") for example
If the selection changes before the timer reaches 2 seconds then the timer should be reset and started over again.
This is to ensure that the lengthy action only launches if the selection has not changed within 2 seconds but I am not familiar with the DispatcherTimer feature of WPF as i am more in the know when it comes to the normal Timer of Windows Forms.
Thanks,
S.
Try this:
private int timerTickCount = 0;
private bool hasSelectionChanged = false;
private DispatcherTimer timer;
In your constructor or relevant method:
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1); // will 'tick' once every second
timer.Tick += new EventHandler(Timer_Tick);
timer.Start();
And then an event handler:
private void Timer_Tick(object sender, EventArgs e)
{
DispatcherTimer timer = (DispatcherTimer)sender;
if (++timerTickCount == 2)
{
if (hasSelectionChanged) timer.Stop();
else MessageBox.Show("Hi there");
}
}
Finally, to make this work, you just need to set the hasSelectionChanged variable when the selection has changed according to your SelectionChanged event.
I've figured the complete code out as such:
DispatcherTimer _timer;
public MainWindow()
{
_myTimer = new DispatcherTimer();
_myTimer.Tick += MyTimerTick;
_myTimer.Interval = new TimeSpan(0,0,0,1);
}
private void ElementFlowSelectionChanged(object sender, SelectionChangedEventArgs e)
{
_counter = 0;
_myTimer.Stop();
_myTimer.Interval = new TimeSpan(0, 0, 0, 1);
_myTimer.Start();
}
private int _counter;
public int Counter
{
get { return _counter; }
set
{
_counter = value;
OnPropertyChanged("Counter");
}
}
private void MyTimerTick(object sender, EventArgs e)
{
Counter++;
if (Counter == 2)
{
_myTimer.Stop();
MessageBox.Show(“Reached the 2 second countdown”);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler e = PropertyChanged;
if (e != null)
{
e(this, new PropertyChangedEventArgs(propertyName));
}
}
look here is the code of how to use DispatherTimer and you can add your own logic in it. that will depends on you..
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(2000);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, object e)
{
// show your message here..
}
To use a DispatcherTimer:
private DispatcherTimer _timer;
public void StartTimer()
{
if (_timer == null)
{
_timer = new DispatcherTimer();
_timer.Tick += _timer_Tick;
}
_timer.Interval = TimeSpan.FromSeconds(2);
_timer.Start();
}
void _timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Hi there");
_timer.Stop();
}
void SelectionChangedEvent()
{
StartTimer();
}

Window service : How to start a Timer at Particular Time

I have seen similar post of setting Timer at particular time ... I Dont want to run timer Whole Day ...I Want to start it at specific Time ..
Most of the suggestion is use Scheduled tasks ...but I want to do it with window service ....
Here is My Service Working Code :
public AutoSMSService2()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
Timer checkForTime = new Timer(5000);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
}
protected override void OnStop()
{
eventLog1.WriteEntry("In onStop.");
}
void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
eventLog1.WriteEntry("Timer Entry");
}
My Timer is working fine and adding Log at 5 sec interval ..But I want to start Timer Lets Say 3:00 PM ...
private static void SetTimer(Timer timer, DateTime due)
{
var ts = due - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
But I am not sure How to Implement it in Code ..
Any suggestion would be Helpful
If you want to do it every day, Hope this will help.
private System.Threading.Timer myTimer;
private void SetTimerValue ()
{
DateTime requiredTime = DateTime.Today.AddHours(15).AddMinutes(00);
if (DateTime.Now > requiredTime)
{
requiredTime = requiredTime.AddDays(1);
}
myTimer = new System.Threading.Timer(new TimerCallback(TimerAction));
myTimer.Change((int)(requiredTime - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
}
private void TimerAction(object e)
{
//here you can start your timer!!
}
here an example with windows form but you can achieve the some thing with windows service
public partial class Form1 : Form
{
private bool _timerCorrectionDone = false;
private int _normalInterval = 5000;
public Form1()
{
InitializeComponent();
//here you calculate the second that should elapsed
var now = new TimeSpan(0,DateTime.Now.Minute, DateTime.Now.Second);
int corrTo5MinutesUpper = (now.Minutes/5)*5;
if (now.Minutes%5>0)
{
corrTo5MinutesUpper = corrTo5MinutesUpper + 5;
}
var upperBound = new TimeSpan(0,corrTo5MinutesUpper, 60-now.Seconds);
var correcFirstStart = (upperBound - now);
timer1.Interval = (int)correcFirstStart.TotalMilliseconds;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
// just do a correction like this
if (!_timerCorrectionDone)
{
timer1.Interval = _normalInterval;
_timerCorrectionDone = true;
}
}

Categories

Resources