Check if timer elapsed in thread - c#

I have a while loop running in my .NET backgroundworker. I would like to end the loop when Timers.Timer reaches 0.
Problem is that since I'm working in another thread (backgroundworker), my timer has to be instantiated in that same thread. So I can't set any private boolean timer_Elapsed. Nether do I know how to give reference of boolean thro event.
Code Example:
private bool timer_Elapsed = false;
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
Set_Timer(timer);
timer.Start();
while(timer_Elapsed) //Has to be a boolean that indicates if timer elapsed
{
this.Do_Proces();
}
}
private void Set_Timer(System.Timers.Timer timer)
{
timer.Interval = 200;
timer.Elapsed += new ElapsedEventHandler(timer_ElapsedEvent);
}
private void timer_ElapsedEvent(object source, ElapsedEventArgs e)
{
timer_Elapsed = true; //I can't set my private boolean since it got instantiated in another thread
}
Particular questions in code. I'm new with this kind of stuff.
Any suggestions? Thanks in advance
EDIT: To clarify, I want the Do_Proces() to run for 200 milliseconds, when that time passed, I want it to stop. When it stops after 200 millisec, I want to and update GUI with data generated in backgroundWorker. Then check if user wants the proces to stop, if not, I want it to run again.. I use the timer because the thread will have to get restarted to much, this will have effect on the main thread as well, effecting the user experience badly.

Is the timer serving any other purpose other than listed here? If not, you may just want to record the current time at the beginning of your BackgroundWorker method, and change the condition on the while loop to check if the required amount of time has elapsed.
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
TimeSpan timeout = TimeSpan.FromMinutes(5);
DateTime start_time = DateTime.Now;
while(DateTime.Now - start_time < timeout)
{
this.Do_Proces();
}
}

Related

Task execution time higher than Timer execution time

I would like to clarify possible code implementaion in case if the code executing withing timerDoJob_Elapsed is getting longer that it should.
So all internal things are gonna be coruppted/canceled and etc when timer fires next time.
Is there any pattern for this kind of problem?
Any clue about make it more stable?
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
If you're using System.Timers.Timer, turn off AutoReset. Then re-enable the timer at the end of your Elapsed method.
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
mytimer.Enabled = true;
}
This way, the timer does not even start again until the task is complete. But make sure to wrap everything in your Elapsed method in try/catch blocks because if an unhandled exception happens there, your timer won't start again.
Another method I've used before is to use a lock in your Elapsed event:
var myLock = new Object();
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
lock (myLock) {
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
}
This way, two instances of the Elapsed event cannot run at the same time. However, there is a caveat: If the task takes longer than two or more iterations of the timer, then you can have iterations adding up in the background. For example, if your timer elapses after 5 seconds, but your task takes 60 seconds to complete, by the time the first one finishes, you'll have 11 waiting.
Timer.Change method giving Timeout.Infinite and 0 as arguments will stop the timer (from MSDN):
If dueTime is zero (0), the callback method is invoked immediately. If
dueTime is Timeout.Infinite, the callback method is never invoked; the
timer is disabled, but can be re-enabled by calling Change and
specifying a positive value for dueTime.
One possible and simple but yet powerful approach is stopping the timer until the whole tasks have ended, and then, start the timer again:
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e)
{
timerDoJob.Change(Timeout.Infinite, 0);
// Use a try-finally so if some tasks throws an exception
// the timer will be re-enabled again anyway
try
{
VeryLongTask1();
VeryLongTask2();
VeryLongTask3();
}
finally
{
timerDoJob.Change(0, 5000);
}
}

Delayed countdown in DispatcherTimer

I have an app which uses DispatcherTimer to manage time, countdown things etc. and I do have multiple counters turned on while app is open. But the time is a little bit delayed, I'd say about 3-5 seconds per minute. This is part of the code I'm using:
DispatcherTimer ob = new DispatcherTimer();
ob.Interval = new TimeSpan(0, 0, 1);
private void bob_Click(object sender, RoutedEventArgs e) //Button starting countdown
{
ob.Start();
tikOb = 140;
ob.Tick += new EventHandler(ob_Tick);
}
void ob_Tick(object sender, EventArgs e)
{
tob.Text = tikOb.ToString();
if (tikOb > 0)
{
tikOb--;
}
else
{
ob.Stop();
tob.Text = "STOPPED";
ob.Tick -= new EventHandler(ob_Tick);
}
//Between these there is a code which is irrelevant in this case.
private void stopob_Click(object sender, RoutedEventArgs e) //Button breaking countdown
{
ob.Tick -= new EventHandler(ob_Tick);
ob.Stop();
tob.Text = "ON";
{
Can anyone tell me why is this happening? Did I do anything wrong inside the code? Oh, I also have another one in the code which uses different variables etc. It's completely separated. Thanks in advance!
The DispatcherTimer is executed on the UI thread. If the UI thread is currently busy doing other work for more than the interval, it will delay the execution of the Timer event and invoke it once it is free of prior work. If you need more precise scheduling, you should go for a time than runs in the background, like System.Threading.Timer or Task.Delay which can be awaited, if you're using .NET 4.5 and above. If you use the Timer and then invoke UI thread logic, you will have to remember to marshal back work to the UI thread.

How to start a BackgroundWorker on a specific time?

I am having a problem in running a backgroundworker on a given specific time.
My code runs the backgoundworker in only one second.
I want to increase the Interval time in my background.
I am using this line of code to run a background in a button click Event:
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Then in backgroundWorker1_DoWork:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.CancelAsync();
}
At last in backgroundWorker1_RunWorkCompleted:
private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
I want to run the background continuously but for every 5 seconds or more than 5.
There would be a great appreciation if someone could help me,
Thanks in advance.
Run-time
Timer class represents a Timer control and used to create a Timer at run-time. The following code snippet creates a Timer at run-time, sets its property and event handler.
Timer t = new Timer();
t.Interval = 2000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(OnTimerEvent);
The event handler code looks like following.
private void OnTimerEvent(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Here is demo : C# Timer Tutorial
Check documentation on msdn : http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
you could add a Timer setting the interval to how often you want the background worker to run and on the timers elapsed event you could start your background worker.
you will want to check that the background worker is not busy before you attempt to start it again though. If this situation occurs then you might consider immediately starting the background worker again when it completes. (if you want it to run at least once every 5 secs)
If you want it to wait 5 seconds after completion, then you need to stop the timer before you start the background worker, then in the background workers completed event you need to reset the timer and start it again.
EDIT
after one of your comments below it seems that you have many backgroundworkers, in which case using one of the other approaches which inserts a delay in the background workers completed event before starting the backgroundworker again is probably a better solution.
You could insert the delay using Thread.Sleep() as has been suggested or you could maybe create a timer in the function and assign a delegate to the timers elapsed event which restarted the background worker. Something along these (untested) lines:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Timer timer = new Timer();
timer.Interval = 5000;
timer.Enabled = true;
timer.Elapsed+=delegate (object sender, ElapsedEventArgs args)
{
backgroundWorker1.RunWorkerAsync();
};
timer.Start ();
}
Do you need it to run exactly every five seconds or not more often than five seconds? If it's the latter you could call Sleep(5000) on the Thread.CurrentThread just before your BackgroundWorker finishes its DoWork() method.
The easiest solution would be to let the thread sleep for 5 seconds in the beginning of backgroundWorker1_DoWork: Thead.Sleep(5000).
Alternatively, you can set a timer in RunWorkerCompleted that expires in 5 seconds and then starts the BackgroundWorker again.
If you want to use BW try this:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Thread.Sleep(5000);//wait for 5s then run it again
backgroundWorker1.RunWorkerAsync();
}
Couldn't you use a Timer to start your BackgroundWorker?

C# timer (slowing down a loop)

I would like to slow down a loop so that it loops every 5 seconds.
In ActionScript, I would use a timer and a timer complete event to do this. How would I go about it in C#?
You can add this call inside your loop:
System.Threading.Thread.Sleep(5000); // 5,000 ms
or preferable for better readability:
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
However, if your application has a user interface you should never sleep on the foreground thread (the thread that processes the applications message loop).
You can try using Timer,
using System;
public class PortChat
{
public static System.Timers.Timer _timer;
public static void Main()
{
_timer = new System.Timers.Timer();
_timer.Interval = 5000;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
Console.ReadKey();
}
static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Do Your loop
}
}
Also if your operation in loop can last more then 5 sec, You can set
_timer.AutoReset = false;
to disable next timer tick until operation finish in loop
But then end end of loop You need again to enable timer like
_timer.Enabled = true;
Don't use a loop at all. Set up a Timer object and react to its fired event. Watch out, because these events will fire on a different thread (the timer's thread from the threadpool).
Let's say you have a for-loop that you want to use for writing to a database every second. I would then create a timer that is set to a 1000 ms interval and then use the timer the same way you would use a while-loop if you want it to act like a for-loop. By creating the integer before the loop and adding to it inside it.
public patial class Form1 : From
{
timer1.Start();
int i = 0;
int howeverLongYouWantTheLoopToLast = 10;
private void timer1_Tick(object sender, EventArgs e)
{
if (i < howeverLongYouWantTheLoopToLast)
{
writeQueryMethodThatIAssumeYouHave(APathMaybe, i); // <-- Just an example, write whatever you want to loop to do here.
i++;
}
else
{
timer1.Stop();
//Maybe add a little message here telling the user the write is done.
}
}
}

BackgroundWorker thread and Timer logic

I've been trying to get the logic right for my timer and backgroundworker thread. Granted I don't fully understand the whole system despite all my reading. the following are excerpts of code concerned:
My polling button :
private void pollStart_Click(object sender, EventArgs e)
{
tst_bgw = new BackgroundWorker();
//mandatory. Otherwise will throw an exception when calling ReportProgress method
tst_bgw.WorkerReportsProgress = true;
//mandatory. Otherwise we would get an InvalidOperationException when trying to cancel the operation
tst_bgw.WorkerSupportsCancellation = true;
tst_bgw.DoWork += tst_bgw_DoWork;
tst_bgw.ProgressChanged += tst_bgw_ProgressChanged;
tst_bgw.RunWorkerCompleted += tst_bgw_RunWorkerCompleted;
tst_bgw.RunWorkerAsync();
}
which I think is right so far
my Background worker thread:
private void tst_bgw_DoWork(object source, DoWorkEventArgs e)
{
m_timer = new System.Timers.Timer();
m_timer.Interval = 1000;
m_timer.Enabled = true;
m_timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
if (tst_bgw.CancellationPending)
{
e.Cancel = true;
return;
}
}
and the elapsed tier event code:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
if (powerVal > 3250)
{
m_timer.Stop();
tst_bgw.CancelAsync();
}
else
{
string pow;
int progressVal = 100 - ((3250 - powerVal) / timerVal);
uiDelegateTest tstDel = new uiDelegateTest(recvMessage);// the recvMessage function takes a textbox as an argument and directs output from socket to it.
pow = construct_command("power", powerVal);
sData = Encoding.ASCII.GetBytes(pow);
if (active_connection)
try
{
m_sock.Send(sData);
Array.Clear(sData, 0, sData.Length);
tstDel(ref unit_Output);// Read somewhere that you can only modify UI elements in this method via delegate so I think this is OK.
m_sock.Send(time_out_command);
tstDel(ref unit_Output);
tst_bgw.ReportProgress(progressVal);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
tst_bgw.ReportProgress(powerVal, progressVal);
powerVal = powerVal + pwrIncVal;
}
I'd just like to know a few other things; am I using the right timer (not that I think it should matter greatly but it was suggested that this might be the best timer for what I want to do) and canI really modify UI elements in the DoWork method only through delegates and if yes are there sepcial considerations to doing so.
Sorry about the long posting and thank you for your time.
There is lots wrong with this code.
1) You aren't disposing of your background worker. BackgroundWorkers must be disposed of after use. They are designed to be used as winforms components and would normally be added to a window via the designer. This will ensure it is created with the form and disposed of when the form is.
2) All you are doing in your dowork method is creating a new timer and running it. There is no point of doing this in a background worker because it will happen so quickly anyway.
3) You will recreate the timer every time you run the background worker again. But you aren't ever stopping or disposing of the old timer, you are just overwriting the member.
I recommend you get rid of the BackgroundWorker completely and just use a timer. Create the timer in the forms constructor and make sure you dispose of it in the forms dispose method. (Or use the designer to add it to the form). In the pollstart_click method just start the timer. (If you have a poll stop method, you can stop the timer in that)
You don't need both a BackgroundWorker and a Timer to accomplish your goal. From what you have posted it looks like you want to have the user click a button which starts a polling process that quits at a certian point.
Your polling model really suggests a timer would work just fine.
If you use a Timer I would Initialize the timer after the InitializeComponent() call with something like
private void InitializeTimer()
{
this.timer = new Timer();
int seconds = 1;
this.timer.Interval = 1000 * seconds; // 1000 * n where n == seconds
this.timer.Tick += new EventHandler(timer_Tick);
// don't start timer until user clicks Start
}
The button_click will simply
private void button_Click(object sender, EventArgs e)
{
this.timer.Start();
}
Then on the timer_Tick you will need to do your polling and you should be able to update your UI from there if the timer is on the UI thread like this
void timer_Tick(object sender, EventArgs e)
{
if( determineIfTimerShouldStop() )
{
this.timer.Stop();
}
else
{
// write a method to just get the power value from your socket
int powerValue = getPowerValue();
// set progressbar, label, etc with value from method above
}
}
However if the timer thread is not on the same thread as the UI you well get an exception while trying to update the UI. In that case you can use the Invoke that DataDink mentions and do something like this
void timer_Tick(object sender, EventArgs e)
{
if( determineIfTimerShouldStop() )
{
this.timer.Stop();
}
else
{
// write a method to just get the power value from your socket
int powerValue = getPowerValue();
// set a label with Invoke
mylabel.Invoke(
new MethodInvoker( delegate { mylabel.Text = "some string"; } )
);
}
}
Given the code you posted you really didn't need to do both a BackgroundWorker and a Timer, but I have had instances where I have used a BackgroundWorker to do work when a timer is called so that I could have a timer update UI periodically and have a manual button to Refresh the UI. But I wasn't updating my UI quite the way you are.
If you still have the need to do both, here is, roughly, how you can flow your app...
Create an
InitailizeBackgroundWorker() method
along with the InitializeTimer so you have
it already initalized before the
Timer fires.
Then set the Timer.Tick
to call the
BackgroundWorker.RunWorkerAsync()
Then you can do all the UI updates from within the RunWorkerAsync by
using the
BackgroundWorker.ReportProgress().

Categories