Click here to Skip to main content
15,884,099 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
See more:
Hello.

I got a User control that is flashing a object and to do that I am using a timer in the Custom Control.
The problem is that I am having 100+ of those controls on one form and they dont flash synchronously and uses a lot of the computers cpu when they all have a running timer.

Are there a smart solution for having just one timer instead of having a timer running for each control?

Thanks.
Posted
Comments
Sergey Alexandrovich Kryukov 1-Nov-11 12:44pm    
Why timer? Also, tag UI library -- always! WPF, Silverlight, Forms, ASP.NET -- what?
--SA
Member 4417892 1-Nov-11 13:33pm    
It's a windows form. Sorry not for meantion that.
I have no experience or knowledge about UI library - actually I dont even know what it is. But I will try read about it and see if that can help me.
phil.o 1-Nov-11 15:09pm    
UI => User Interface
Tips to solve UI problems are closely bound to the technology/framework that is used.
Edit: sorry, wrong place. I was replying to Member 4417892...

How about having one timer for the class which is created when it's first needed?

class MyCleverControl : UserControl {
 private static Timer timer;
 private static Timer Timer {
  get {
   if(timer == null) { timer = new Timer(TimerInterval); timer.Start(); }
   return timer;
  }
 }

 public MyCleverControl(){
  Timer.Tick += (s, e) => { whatever; };
 }
}


If you remove or dispose of the form that it's on, you'll have to write some tidying up code to stop the timer sitting around and firing events forever (and, in fact, to let the user control get garbage collected at all).
 
Share this answer
 
Comments
Member 4417892 1-Nov-11 13:29pm    
I got a timer right now in the control, but everytime I create the control it also creates a new timer.
If I add your code to my control I believe it still would be the same, that I have an timer everytime for each control I create?

Or will you add this timer class seperately, and then call it from the usercontrol ?
BobJanova 1-Nov-11 13:38pm    
It's static, that means there's only one instance of the timer created.

Ed: remove the timer that you add in the instance code now, obviously.
Member 4417892 2-Nov-11 4:26am    
Stupid me!
Thanks, making it static ofcourse solved it all :)
Of course, 100+ timers is way to many to be reasonable. Let's try to reduce the number of timers. Consider just one. It will be much better: do all the processing for all the controls in the handler or callback of this timer (there are three type of timer in .NET, the one who will find them all is a cool guy :-)). Depending on what you want to do with all the controls, you can supply an array of all controls, or a class instance with several arrays of controls, one property per control type. I don't want to go into further detail in this solution, as the number of timers can be further reduced.

Here is the best solution: use 0 (zero) timers! You don't need any timers for such thing, and using them is not easy and error-prone. Instead, use a separate thread. In the thread, you need to sleep for some period of time (System.Threading.Thread.Sleep), which uses zero CPU time until a thread is waken up by an expiration of time or Abort. When your main form is about to close, just abort this thread using System.Threading.Thread.Abort. Don't try to pause/resume thread if you want it. Instead, use the class System.Threading.ManualResetEvent to throttle the thread.

See:
http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx[^],
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx[^].

Now, how this thread can work with UI?

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
v2
Comments
Paulo Zemek 1-Nov-11 13:12pm    
If using a lot of timers is bad, using a lot of threads is even worse. Using abort is even a worse practice.
Sergey Alexandrovich Kryukov 1-Nov-11 14:21pm    
Paulo,

1) my idea is using only one extra thread; 2) you mix up Thread.Abort with old TerminateThread. Do you know how it works (exception seeding)? This kind of Thread.Abort is the greatest invention on threading ever made. It gives you full control over the clean-up (post-mortal) action. It was invented well before .NET emerged and I did not even hope that it will be "officially" implemented. I did not hope because there was a big misunderstanding: the creators of OS did not understand requirements of real-life applications. If you could explain me exact problems with Abort, I would appreciate it very much.

Thank you,
--SA
Paulo Zemek 1-Nov-11 14:26pm    
No... I am not confusing. I even wrote an articles on why "using" keyword is not abort safe. But the fact is, Abort may happen at any IL instruction. For example, between the allocation of an unsafe object and just before storing its value into a field, so even the finalizer will not solve the problem.
It is much simpler (if a thread is really used) to have a bool flag. So, when finishing, set the flag (ended) to true, and then also signal the ManualResetEvent. So the thread will be terminated at the right point.
Sergey Alexandrovich Kryukov 1-Nov-11 15:14pm    
Bool flag is a bit safer, but it's impossible in many cases. Imaging you have a numeric library which integrates some equation, and the time for all iterations on all levels is unknown. What, you are going to inject a test for Boolean flag here and there? Not realistic. I can give you more examples. At the same time, Abort is perfectly safe when you know how to use it.
--SA
Sergey Alexandrovich Kryukov 1-Nov-11 15:23pm    
The problem of allocation you have discussed is resolved using Thread.BeginCriticalRegion... Thread.EndCriticalRegion. So, so far you did not give me a compelling argument against Abort. And, hey, I do know you are a master of threading: one day you provided me some criticism, so I fixed my article and code; and I appreciated it as your help. Here, this is not the case, at least at the moment...
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900