If is there 1 thread per Timer ?
for example :
class MyObj
{
private Timer _timer;
public MyObj()
{
Initialize();
}
private void Initialize()
{
_timer = new Timer(2000);
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
}
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("MyObj !");
}
}
class Program
{
private static Timer _timer;
private static void Main(string[] args)
{
_timer = new Timer(500);
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
MyObj mo = new MyObj();
Console.Read();
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Program !");
}
}
Is there 2 threads ?
The timer uses the ThreadPool so at most you'd be using 2 threads. However, as threads in the ThreadPool are recycled it may end up using the same thread twice, or two threads but not simultaneously.
The timer itself doesn't cause the creation of a thread.
Also, if your timer never ticks - it won't post any work to the ThreadPool so in essence won't "cost" you any threads.
Be aware though that the tick thread is indeterminate... the thread you create the timer on is not the thread the tick will occur on. Any logic in your tick needs to be aware that it could be running in parallel with something else in the class.
No there isn't a reserved thread per timer. The event gets scheduled on a thread-pool thread, and the timer doesn't block a thread while the event handler isn't running. Since there are multiple thread-pool threads, event handlers still need to be thread-safe.
The documentation states:
If the SynchronizingObject property is Nothing, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.
Related
I have a BackgroundWorker _worker
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
_timer = new System.Timers.Timer();
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Interval = 5000;
_timer.Start();
}
When it gets to the line _timer.Start() it thinks it has finished so fires the RunWorkerCompleted event.
I don't want it to finish until the _timer.Interval time has been reached and the _timer Elapsed event has been trigger:
void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
for (int i = 1; i < 20; i++)
{
if (listBox1.InvokeRequired)
listBox1.Invoke((Action)(() => listBox1.Items.Add("Do Things Thread")));
else
listBox1.Items.Add("Do Things Completed");
_worker.ReportProgress((int)(((decimal)i / (decimal)20) * 100));
Thread.Sleep(1000);
}
_timer.Stop();
}
Because I need the BackgroundWorker to report back some progress.
How do I do this. I need it to run on a different thread.
So to round up the discussion and the solution.
System.Timers.Timer will automatically thread the timer event for you unless you supply a sync object, as discussed in MSDN:
If the SynchronizingObject property is null, the Elapsed event is
raised on a ThreadPool thread. If processing of the Elapsed event
lasts longer than Interval, the event might be raised again on another
ThreadPool thread. In this situation, the event handler should be
reentrant.
This means that the background worker becomes superfluos. You can simply have your timer event code run as is (as it uses invoke to interact with the UI anyhow).
It does mean that these events can run concurrently if they take a long time. However, you can of course stop and start the timer in the event callback.
Your _timer_Elapsed event is on a different thread. The instance of timer will expire as soon as the control flow passes through the _worker_DoWork function. The scope of your timer object variable is restricted to the function and hence it will not work this way.
I would suggest that you put put Thread.sleep(5000) in the timer _worker_dowork function itself. It will not affect your application as the thread will sleep and the gui will still be responsive.
I think, just by playing around with what I've done, is that I've invoked the progress bar, so I don't need the ReportProgress:
_worker.ReportProgress((int)(((decimal)i / (decimal)20) * 100));
Changed to :
if (progressBar1.InvokeRequired)
progressBar1.Invoke((Action)(() => progressBar1.Value = (int)(((decimal)i / (decimal)20) * 100)));
else
progressBar1.Value = (int)(((decimal)i / (decimal)20) * 100);
That means, I don't have to suspend the BackgroundWorker, and the timer was invoked on a different thread and will remain until disposed of????
During debugging I can see that after Timer.Stop() or Timer.Enabled = false commands are executed, Timer is still running (Timer.Enabled = true). How is that possible?
This is possible when you stop the timer on a worker thread. For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Timer timer1;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
timer1 = new Timer();
timer1.Interval = 3000;
timer1.Start();
var t = new System.Threading.Thread(stopTimer);
t.Start();
}
private void stopTimer() {
timer1.Enabled = false;
System.Diagnostics.Debug.WriteLine(timer1.Enabled.ToString());
}
}
Output:
True
The timer must be stopped by the UI thread, the class takes care of it automatically. Quite similar to Control.BeginInvoke(). There's an explicit race, the Tick event handler can run after you stopped it. This can also happen on the UI thread if the very first timer you create is created on a worker thread. A splash screen for example. That's not healthy, you ought to fix that.
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.
bear also in mind
Calling Stop on any Timer within a Windows Forms application can cause messages from other Timer components in the application to be processed immediately, because all Timer components operate on the main application thread. If you have two Timer components, one set to 700 milliseconds and one set to 500 milliseconds, and you call Stop on the first Timer, your application may receive an event callback for the second component first. If this proves problematic, consider using the Timer class in the System.Threading namespace instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.stop.aspx
public void EnableTimer(bool state)
{
if (this.InvokeRequired) {
this.Invoke(new Action<bool>(EnableTimer), state);
} else {
this.Timer1.Enabled = state;
}
}
Try this code...
There is a problem with standard System.Timers.Timer behaviour. The timer raise Elapsed event with some interval. But when time of execution inside Elapsed event handler exceed timer interval then thread pool begin queuing event handling. This is a problem in my case. This is because with my Elapsed event handler I fetch some data from database and doing something with it and finally save results back to database. But data handling should be provided only once. So, is there a way to prevent from queuing elapse events for System.Timers.Timer.
As illustration for this issue you can consider next test program:
public class EntryPoint
{
private static void TimeProc(object state, ElapsedEventArgs e)
{
Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(20000);
}
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> for finishing\n\n");
ThreadPool.SetMaxThreads(10, 10);
System.Timers.Timer MyTimer = new System.Timers.Timer(1000);
MyTimer.Elapsed += new ElapsedEventHandler(TimeProc);
MyTimer.Start();
Console.ReadLine();
MyTimer.Stop();
}
}
And possible output will be as here:
Current time 03.02.2011 0:00:09 on the thread 4
Current time 03.02.2011 0:00:10 on the thread 5
Current time 03.02.2011 0:00:12 on the thread 6
Current time 03.02.2011 0:00:13 on the thread 7
Current time 03.02.2011 0:00:14 on the thread 8
Current time 03.02.2011 0:00:15 on the thread 9
Current time 03.02.2011 0:00:16 on the thread 10
Current time 03.02.2011 0:00:17 on the thread 11
Current time 03.02.2011 0:00:18 on the thread 12
Current time 03.02.2011 0:00:19 on the thread 13
Current time 03.02.2011 0:00:30 on the thread 4
Current time 03.02.2011 0:00:30 on the thread 5
Possible solutions:
1) It was inspired by:C# Timer vs Thread in Service
And has a code like here regarding to mentioned above sample:
public class EntryPoint
{
private static System.Timers.Timer MyTimer;
private static void TimeProc(object state, ElapsedEventArgs e)
{
Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(20000);
MyTimer.Enabled = true;
}
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> for finishing\n\n");
ThreadPool.SetMaxThreads(10, 10);
MyTimer = new System.Timers.Timer(1000);
MyTimer.AutoReset = false;
MyTimer.Elapsed += new ElapsedEventHandler(TimeProc);
MyTimer.Enabled = true;
Console.ReadLine();
}
}
2) Second way is about SynchronizingObject, but it is a valuable only for Windows form application or required additional development of code for implementing object that would be implements ISynchronizeInvoke interface. More about this way you can find here
So, for now I will prefer first solution.
What I usually do in this case is stop the timer at the start of the Elapsed handler and start it again at the end. This way, you are only handling one tick at a time.
UPDATE:
Per the MSDN link, I think what they mean is that you can set your own flag (but still have the ticks come in), but thread safety measures should be taken as well.
I would say simply stop it and then start it after your lengthy execution like this.
tmr.Stop();
//Your lengthy execution code goes here
tmr.Start();
The behavior you are seeing is by design. Either set a SynchronizingObject on the timer, or use another timer (such as System.Threading.Timer) that doesn't tick on multiple threads.
I just create a static flag variable. This way my timer keeps running, but the code is simply bypassed if it the method has not completed before the next timer cycle.
In the method used for the timer, test if an event is in progress.
Timer_Method_Called()
{
if (eventInProgress == 0)
{
// flag event as in progress
eventInProcess == 1;
// perform code....
// after code is complete, allow the method to execute
eventInProgress == 0;
}
}
Since none of the answers are thread safe, let me propose one that is:
void oneHundredMS_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
if (setTimerBodyRunning()) { //only proceed to body if it is not already processing; setTimerBodyRunning must be thread-safe
// here you do your long running operation
setTimerBodyFinished();
}
}
As you can see, the timer handler first checks to see if it is not already running, and only proceeds to the body if false is returned. If true is returned, then the handler quickly returns and ticks do not queue (which they would have had a simple lock statement been used). Here are the definitions for setTimerBodyRunning and setTimerBodyFinished:
private bool setTimerBodyRunning() {
bool retVal = false;
lock (timerBodyRunning) { //timerBodyRunning is type object and it holds a bool.
//The reason it is object and not bool is so it can be locked on to ensure thread safety
if (!((bool)timerBodyRunning)) {
timerBodyRunning = true;
retVal = true;
}
}
return retVal;
}
private void setTimerBodyFinished() {
lock (timerBodyRunning) {
timerBodyRunning = false;
}
}
Here's how you'd initialize and start the timer:
object timerBodyRunning = new object();
timerBodyRunning = false;
System.Timers.Timer timerFrequency100MS = new System.Timers.Timer();
timerFrequency100MS.Interval = FREQUENCY_MS; //it will fire every 100 milliseconds
timerFrequency100MS.Elapsed += new System.Timers.ElapsedEventHandler(oneHundredMS_Elapsed);
timerFrequency100MS.Start();
I have a kinda awkward problem, I'm working with C# and WPF in .NET 4.0 and what I need is a timer that will create only one thread but it will need to work in the background, so not in the main thread, the problem is using System.Windows.Forms.Timer or DispatchTimer will automatically force it to work on the main thread and be influenced by the UI, on the other side using System.Timers.Timer or System.Threading.Timer will create a new thread for every cycle that overpasses the time interval, this will happen since the code in the elapsed timer event is a bit big, although part of it is sent further to a background worker.
so I was thinking if it's possible to force, say the System.Timers.Timer, to work in the background and never spawn to more then one thread, also I am opened to other suggestions
Use System.Timers.Timer, which fires its elapsed event handler on a ThreadPool thread. As soon as you enter the event handler, stop the timer. At the end of your event handler, start the timer and it will start counting down from the beginning of its interval.
Here's a simple example with a 100ms timer that spends 2 seconds in it's elapsed event handler:
static void Main(string[] args)
{
System.Timers.Timer myTimer = new System.Timers.Timer(100);
myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
myTimer.Start();
Console.ReadLine();
}
static void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
((System.Timers.Timer)sender).Stop();
Console.WriteLine(DateTime.Now.ToString("HH.mm.ss"));
System.Threading.Thread.Sleep(2000);
((System.Timers.Timer)sender).Start();
}
Just use a System.Threading.Timer with a period of 0 so that the callback runs only once. When everything is done, recharge the timer so it will fire again later. You'll have guaranteed only ever one thread running this way.
DispatcherTimer has a constructor overload that lets you do exactly what you want.
Use it in the context of your thread:
using System.Threading;
using WpfThreading = System.Windows.Threading;
...
Thread t = new Thread(() =>
{
var interval = TimeSpan.FromSeconds(3.0);
var priority = WpfThreading.DispatcherPriority.Background;
EventHandler callback = (a, e) => { };
var dispatcher = WpfThreading.Dispatcher.CurrentDispatcher; // dispatcher for this thread
WpfThreading.DispatcherTimer dt = new WpfThreading.DispatcherTimer(interval, priority, callback, dispatcher);
bool sameDispatchers = WpfThreading.Dispatcher.CurrentDispatcher == this.Dispatcher; // false
});
t.Start();
Got a quick question on creating a C# thread.
It needs to run every 10 minutes
The worker will do work then go into sleep for another 10 minutes
It can also be triggered to run immediately by calling Trigger()
It can be stopped by calling Stop()
I've created one with ManualResetEvent, which is set when Stop() is called. This works well but do I need to create another ManualResetEvent or wait handle in order to be able to trigger the worker immediately?
If by Stop you mean Stop waiting and don't run again then I think a Threading.Timer will be a good (lean) choice.
You can activate a timer with a DoWork() method and a 10 minutes interval. It will use the ThreadPool which seems the best choice here. Trigger() can queue DoWork directly on the Pool and Stop() can deactivate the Timer. DoWork() shouldn't use Sleep() and be suitable for the ThreadPool.
Using a timer here makes sense. Here's a quick code-snippet which I haven't tested.
private System.Timers.Timer _timer = null;
public void Constructor()
{
_timer = new System.Timers.Timer(600000);
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void ForceDoWork()
{
//unsubscribe to timer event, so work dowsnt get fired twice
_timer.Elapsed -= new ElapsedEventHandler(t_Elapsed);
StartWorking();
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void StartWorking()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkToBeDone));
}
private void WorkToBeDone(object state)
{
//work here
}
public void t_Elapsed(object sender, ElapsedEventArgs e)
{
StartWorking();
}
Yes, you'll need another wait handle to force thread to execute. You'll basically have to WaitOne for this handle for 10 minutes, thus either elapsing a timeout or continuing whenever the wait handle becomes signalled.
Don't forget to switch that handle to a non-signalled state, though.