I have a method that I want to call a method (will mention as myFanc) in seperated thread every 3 seconds
The code below can easly do it,
Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler( myFanc );
myTimer.Interval = 3000;
myTimer.Start();
The code above may cause myFanc to be called while another call to myFanc isn't finished yet
My problem is that I also want myFanc to finished before I will call her agian, so basically I want to call the method in seperated thread every 3 seconds after myFanc is finished, how can I do it?
I don't mind if the solution won't use Timer class, I just want this behavior to work..
Set the AutoReset property of your timer to false, then, at the end of your event handler (i.e. "myFanc"), call the Start method of your timer again.
Do not use a timer, loop in the thread calling "myfanc" and use
Thread.Sleep(3000);
to insert the desired delay.
At the top of myFunc put this
myTimer.Enabled = false;
and at the end when it is finished put this
myTimer.Enabled = true;
It will cause that you will temporairly disable the Timer while function is executing
This is the solution I used - thanks to Jim
using System;
using System.Timers;
using System.Threading;
class myApp
{
public static void Main()
{
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler( myFanc );
myTimer.Interval = 1000;
myTimer.AutoReset = false;
myTimer.Start();
while ( Console.Read() != 'q' )
{
; // do nothing...
}
}
public static void myFanc(object source, ElapsedEventArgs e)
{
Console.Write("\r{0}", DateTime.Now);
Thread.Sleep(3000); //the sleep here is just to test the method, wait to be finished before another call the myFanc method is being performed
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(myFanc);
myTimer.Interval = 1000;
myTimer.AutoReset = false;
myTimer.Start();
}
}
2 methods than I can think of right now
Stop and start the timer inside the myFanc method This ensures 3 seconds between each run
Wrap your code in myFanc inside a lock, this will just skip a turn if it's not finished.
Make sure you use the correct timer.. system.threading.timer is a seperate thread. The timer class in windows.forms (or something like that) isn't
Use a thread and Thread.Sleep(x) like so
Thread thread = new Thread(new ThreadStart(myTimer));
thread.Start();
void myTimer()
{
while (!exit)
{
myFunc();
Thread.Sleep(3000);
}
}
Related
In my application I'm using two Timer, each Timer use a BackgroundWorker. Here the declaration:
DispatcherTimer timer1 = new DispatcherTimer();
DispatcherTimer timer2 = new DispatcherTimer();
BackgroundWorker worker1 = new BackgroundWorker();
BackgroundWorker worker2= new BackgroundWorker();
I using timer1 for perform an heavy method with a BackgroundWorker and timer2 for execute another BackgroundWorker that check the content of a file.
In this way I assign the event to BackgroundWorkers:
worker1.DoWork += worker_DoWork;
worker1.RunWorkerCompleted += worker_RunWorkerCompleted;
worker1.WorkerSupportsCancellation = true;
worker2.DoWork += worker_DoWork2;
worker2.RunWorkerCompleted += worker_RunWorkerCompleted2;
worker2.WorkerSupportsCancellation = true;
Now timer1 have a range of 15 minutes so the BackgroundWorker execute the heavy method each 15 minutes. And timer2 have a range of 1 second. With the timer1 all working good, but the problems are coming when I've added the timer2.
As I said before this timer allow me to start a method that read a file through the worker2, this file have a property, if this property change I need to perform some special activity. Until here no problem.
What I did is the following:
//This method is called by MainWindow
public ReadFile()
{
//before this I already assigned to timer1 the tick event and start
timer2.Tick -= new EventHandler(Event_Tick);
timer2.Tick += new EventHandler(Event_Tick);
timer2.Interval = new TimeSpan(0, 0, 1);
timer2.Start();
}
This is the Tick event associated to timer2
private void Event_Tick(object sender, EventArgs e)
{
if (!worker1.IsBusy) //I skip the reading, worker1 is busy
{
timer1.Stop(); //stop the first timer
worker2.RunWorkerAsync();
}
else
{
Console.WriteLine("worker1 is busy!");
}
}
I don't need to add here the DoWork, is just a parsing of a file, very useless for the question. When worker2 complete the task I did this:
private void worker_RunWorkerCompleted2(object sender, RunWorkerCompletedEventArgs e)
{
timer1.Start();
ReadFile();
}
How you can see I start the timer1 again, and execute again the ReadFile method. Now if timer1 has reached the interval, so 15 minutes has passed, should execute the timer1.Tick += new EventHandler(Heavy_Tick); that execute the DoWork to worker1. But the timer1 never start.
I can't figure out to this, what am I doing wrong?
Now I get it!
You want to execute worker1 every 15 minutes and worker2 every second but only when worker1 is not busy. Your problem is this here:
if (!worker1.IsBusy) //I skip the reading, worker1 is busy
{
timer1.Stop(); //stop the first timer
worker2.RunWorkerAsync();
}
and this:
public ReadFile()
{
//before this I already assigned to timer1 the tick event and start
timer2.Tick -= new EventHandler(Event_Tick);
timer2.Tick += new EventHandler(Event_Tick);
timer2.Interval = new TimeSpan(0, 0, 1);
timer2.Start();
}
Set both timer intervals and tick event handlers during startup, e.g. Form_Load()or at the beginning of Main(). Start them there too. You should not have to stop any timer at all!
By setting the interval, all you have to do is handle the Tick() event. Remove your .Start() and Stop() calls from your WorkerCompletedand Tick methods and you should do fine.
So a lot could be going on here but you should make sure that:
You timer isn't storing it's old progress and you are checking for a certain length of time before stopping. This will automatically cause the timer to stop when restarting.
The timer.stop() function is not disposing your object to an un-restart-able state.
You aren't accessing the timer variable through some pointer that is maintain a stopped value. (Unlikely but annoying when it happens)
I'd personally consider just pausing the timer and resetting the progress, instead of fully stopping it since this is causing issues.
How can I restrict timer thread execution time? I have long running timer work that should work no more than 30 seconds.
The only way to do this is to have a second thread (possibly the one that created the worker thread) monitor and then kill it or gracefully call it to quit immediately. Killing threads you should avoid, and only use as the last resort. Here is example how:
Thread t = new Thread(myLongThreadProc);
t.Start();
Thread.Sleep(30000);
t.Abort();
By 'gracefully call it to quit', I mean to set some stop variable to some value, and give the thread some short time to quit itself, otherwise you kill it. But it is the design of your thread function to make it actually quit. Here is the sample code:
Thread t = new Thread(myLongThreadProc);
threadRun = true;
t.Start();
Thread.Sleep(30000);
threadRun = false; //this variable is monitored by thread
if (!t.Join(1000)) //inside your thread, make sure it does quit in one second
{ //when this variable is set to false
t.Abort();
}
And should I mention that your caller thread does not have to sleep for 30 seconds, but you can use a timer instead (if it is a form thread) or do something useful and check periodically - or have a third worker thread just counting 30 seconds...
Just have your worker method start a 30-second timer and check to see if it's elapsed as your worker does its thing:
bool timerElapsed;
public void DoWork()
{
timerElapsed=false;
System.Timers.Timer timer = new System.Timers.Timer(30000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
while (true)
{
if (timerElapsed)
{
// handle 30-sec elasped error
break;
}
// continue doing work and break when done
}
timer.Stop();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timerElapsed = true;
}
I have two alternative using timer or using sleep, I need to call a method every 3 seconds after this method is finished, I wrote basic example to demonstrate what I mean:
public static void Main()
{
new Thread(new ThreadStart(fooUsingSleep)).Start();
callToMethodAfterInterval(new Action<object, ElapsedEventArgs>(fooUsingTimer), 3000);
}
public static void fooUsingSleep()
{
Console.WriteLine("Doing some consuming time work using sleep");
Thread.Sleep(3000);
fooUsingSleep();
}
public static void fooUsingTimer(object dummy, ElapsedEventArgs dummyElapsed)
{
Console.WriteLine("Doing some consuming time work usning timer");
callToMethodAfterInterval(new Action<object, ElapsedEventArgs>(fooUsingTimer), 3000);
}
public static void callToMethodAfterInterval(Action<object,ElapsedEventArgs> inMethod, int inInterval)
{
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(inMethod);
myTimer.Interval = inInterval;
myTimer.AutoReset = false;
myTimer.Start();
}
So my questions are
1)Can I wrote the code with the timer more elegant? Means removing the call to the callToMethodAfterInterval method from fooUsingTimer, make the timer one or two lines, and remove the dummy variables from the declaration of fooUsingTimer?
2)I understand sleep isn't busy waiting (http://www.codeproject.com/KB/threads/ThreadingDotNet.aspx)
So I don't found justification to use the timer option here, because the sleep is more simple, what is better to use, the timer version or the sleep one?
3)I know that Timers.timer is thread safe, does it can help me in the behavior I want to implement?
Thanks.
Do you realize that fooUsingSleep is calling itself over and over? It will eventually generate a stack overflow.
If you are using timer, it can be as simple as this:
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 3000;
t.Tick += new EventHandler((o,ea) => Console.WriteLine("foo"));
The real context of your program matters too.
The sleep option 'wastes' a Thread, not a problem in a small console app but in general not a good idea.
You don't need to restart the timer, the following will keep ticking:
static void Main(string[] args)
{
var t = new System.Timers.Timer(1000);
t.Elapsed += (s, e) => CallMeBack();
t.Start();
Console.ReadLine();
}
Sleep will do the trick, Timer on the other hand has been designed for that exact purpose, conventions are better and they will usually make your code more understandable.
I know it sounds stupid, but I've tried everything to stop a timer, but the timer won't stop. I'm working on a game and i would appreciate if someone could tell me how to stop a timer.
If you are using System.Timers.Timer stopping is performed by one of the options:
//options 1
timer.Enabled = false
//option 2
timer.Stop()
if you are using System.Threading.Timer, use this method
timer.Change(Timeout.Infinite , Timeout.Infinite)
if you are using System.Windows.Forms.Timer, use this method
timer.Stop();
So to add to the previous answers, in case you are using the System.Threading.Timer class,
this will stop it permanently with no further chance to use the same instance:
timer.Dispose()
otherwise:
timer.Change(Timeout.Infinite, Timeout.Infinite)
System.Windows.Forms.Timer: timer.Enabled = false;
System.Threading.Timer: timer.Change(Timeout.Infinite, Timeout.Infinite);
System.Timers.Timer: timer.Enabled = false; or timer.Stop();
With each of the timers in the .NET framework, it's possible that the timer fires just before you stop it, so you'll see the callback after you stop it.
You'll need to use something like an asynchronous callback context: use a bool set to true when you want the timer running, and set it to false when you stop it. Then have your callback check your context to see if it should really run or not.
Assuming you are making use of the System.Windows.Forms.Timer; since there was no explicit reference to anything else...if that is the case...
System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
myTimer.Stop();
Depends on the timer. If it is from threading namespace, dispose of it and recreate it when you need to, or have your timer delegate wait on reset event(see msdn). System.Timers namespace has a start and stop method.
I also ran into the similar problem many times.
//Timer init.
var _timer = new System.Timers.Timer
{
AutoReset = true,
Enabled = true,
Interval = TimeSpan.FromSeconds(15).TotalMilliseconds //15 seconds interval
};
_timer.Elapsed += DoSomethingOnTimerElapsed;
//To be called on timer elapsed.
private void DoSomethingOnTimerElapsed(object source, ElapsedEventArgs e)
{
//Disable timer.
_timer.Enabled = false; //or _timer.Stop()
try
{
//does long running process
}
catch (Exception ex)
{
}
finally
{
if (_shouldEnableTimer) //set its default value to true.
_timer.Enabled = true; //or _timer.Start()
}
}
//somewhere in the code if you want to stop timer:
_timer.Enabled = _shouldEnableTimer = false;
//At any point, if you want to resume timer add this:
_timer.Enabled = _shouldEnableTimer = true;
Why to do so?
Lets assume, the code inside the try block takes more time. So, by the time you disable timer (_timer.Enabled = false or _timer.Stop()), there is high possibilty that the code inside try block is still executing. Hence, after completion of the task when it comes to finally, it is again enabled if there is no flag(_shouldEnableTimer) check. Therefore, I prevent your problem by adding an additional flag check.
For more clarity, please go through the code and the added comments. Hope this helps.
Can i create successfully a timer clock on a thread? i'm creating one but it doesn't seem to work that well. My app is a multi-thread app that has to start a timer on a thread when ever a certain event happens. The timer is placed in every client connection. The clock doesn't work until i close my winform(i don't know why) . Is there anything in particular that i should know about timers in threads ?
Here is my timer code :
timer1.Interval = 1000;
timer1.Tick += new EventHandler(timer_Tick);
timer1.Enabled = true;
timer1.Start();
You might try to use System.Threading.Timer, which is basically a timer that's in a separate thread. You might also consider using a WaitHandle that's never fired and then using WaitOne(1000, false) to wait for a second.
Try this:
public void EnableTimer()
{
if (this.InvokeRequired)
this.Invoke(new Action(EnableTimer));
else
this.timer1.Enabled = true;
}