I agree that title doesn’t promise a lot of interesting stuff at first glance especially for experienced .net developers. But unless you encounter some issue due to incorrect usage of timers you will never think that root is in timers.
System.Threading.Timer vs. System.Windows.Forms.Timer
In few words what are differences between Threading and Forms timers just to start with something.
System.Threading.Timer executes some method on periodic bases. But what is interesting is that execution of method is performed in separate thread taken from ThreadPool. In other words it calls QueueUserWorkItem somewhere internally for your method at specified intervals.
System.Windows.Forms.Timer ensure as that execution of our method will be in the same thread where we’ve created timer.
What if operation takes longer than period?
Let’s now think what will happen if the operation we set for execution takes longer than interval.
When I have following code:
my application behaves well – prints “a” twice a second. I took a look for number of threads in Task Manager and it stays constantly (7 threads).
Let now change following line: Thread.Sleep(500) to Thread.Sleep(8000). What will happen now? Just think before continue to read.
I’m almost completely sure that you predicted printing “a” every second after 8 seconds have passed. As you already guessed each of the “a” printings are scheduled in separate threads allocated from ThreadPool. So… amount of threads is constantly increasing… (Every 1.125 seconds :) )
Issue I’ve been investigating
Some mister X also figured out that Console.WriteLine(“a”) is critical and should run in one thread, at least because he is not sure how much does it take to execute Thread.Sleep(500). To ensure it will run in one thread he decided to have lock, like in code below:
Yes, this code ensures that section under lock is executed in one thread. And you know this code works well unless your execution takes few hours and you will be out of threads and out of memory. :) So that is an issue I’ve been investigating.
My first idea was System.Windows.Forms.Timer
My first idea was to change this timer to the System.Windows.Forms.Timer, and it worked well in application, but that application is able to run in GUI and WinService modes. But there are so many complains over interned to do not use Forms.Timer for non UI stuff. Also if you put Forms.Timer into your console application it will simply not work.
Why System.Timers.Timer is good toy?
System.Timers.Timer is just wrapper over System.Threading.Timer, but what is very interesting is that it provides us with more developer-friendly abilities like enabling and disabling it.
My final decision which fixes issue is to disable timer when we are diving into our operation and enable on exit. In my app timer executes every 30 seconds so this could not be a problem. Fix looks like:
And it looks that we don’t need lock there, but I left it there just to be sure is case if SomeOperation will be called from dozen of other threads.
MAKE DECISION ON TIMER BASING ON THIS TABLE (from msdn article)
|Timer event runs on what thread?||UI thread||UI or worker thread||Worker thread|
|Instances are thread safe?||No||Yes||No|
|Familiar/intuitive object model?||Yes||Yes||No|
|Requires Windows Forms?||Yes||No||No|
|Timer event supports state object?||No||No||Yes|
|Initial timer event can be scheduled?||No||No||Yes|
|Class supports inheritance?||Yes||Yes||No|
|* Depending on the availability of system resources (for example, worker threads|
I hope my story is useful and when you will be searching like “C# Timer Threads issues” or “Allocation of threads when using timer” you will find my article and it will help you.
Today I was playing with exception handling and threading in .NET. It was really fun.
Do you know guys that like to have everything in global try-catch block? I have two news for them.
Exception will not be caught in try-catch block if it was thrown in another thread. Those guys also could think that Application.ThreadException could help them to catch those.
But indeed this event fires only if exception has been thrown as result of Windows message or any other code that runs in same thread were your WinForms application lives. I tried to use two timers to verify that.
System.Windows.Forms.Timer – which ensures that code you have in your tick method runs in the same thread as your application. In this case I got message box.
System.Threading.Timer – which runs in separate thread, so my app just crashed.
But if those guys are writing all code in Form1.cs file… then maybe it worth for them to have handling of Application.ThreadException event :)
There is event which will be fired when exception is thrown from any code/thread withing your application domain. It is AppDomain.UnhandledException and it occurs when exception is not caught.
Lets take a look on code snippet that shows this:
To test this I created Threading.Timer and fired it every 2 seconds and throwing exception on each tick, I put breakpoint into event. I got everything expected and application after that failed.
But one of our smart guys could guess to put Thread.Sleep(1000000); into handler code like below:
Everyone is happy. Exception is thrown each 2 seconds or less and UI continue to respond. I hope you already see what is wrong with all of this.
This screenshot talks for itself:
And as you know process could have up to 1024 threads. My process is not exclusion and it also crashed after reached that number.
Ok, looks like guys should change their mind.
Hope it was a bit fun.
In recent time I was interacted with multithreading in .NET.
One of the intersting aspects of it is performance. Most of books says that we should not overplay with performance, because we could introduce ugly-super-not-catching bug. But since I’m using multithreading for my educational purposes I allow myself play with this.
Here is some list of performance tips that I’ve used:
1. UnsafeQueueUserWorkItem is faster than QueueUserWorkItem
Difference is in verification of Security Privileges. Unsafe version doesn’t care about privileges of calling code and runs everything in its own privileges scope.
2. Ensure that you don’t have redundant logic for scheduling your threads.
In my algorithm I have dozen of iterations on each of them I perform calculations on long list. So in order to make this paralleled I was dividing this list like [a|b|c|…]. My problem was in recalculating bounds on each iteration, but since list is always of the same size I could have calculating bounds once. So just ensure that don’t have such crap in your code.
3. Do not pass huge objects into your workers.
If you are using delegate ParameterizedThreadStart and pass lot of information with your param object it could decrease your performance. Slightly, but could. To avoid this you could put such information into some fields of the object that contains method for threading.
4. Ensure that you main thread is also busy guy!
I had this piece of code:
Do you see where I have performance gap? Answer is in utilizing my main thread. Currently it is only scheduling some number of threads (GridGroups) to do some work and than it waits for them to accomplish. If we divide work to approximately equivalent partitions, we could gave some work to our main thread, and in this way waiting time will be eliminated.
Following code gives us persormance increase:
5. ThreadPool and .NET Framework 4.0
Guys, from Microsoft improved performance of the ThreadPool significantly! I just changed target framework of my project to the .Net 4.0 and for worst cases in my app got 1.5x time improvement.
Looking forward that I also could create more sophisticated synchronization with Monitor.Pulse() and Monitor.WaitOne().
Good Threading Reference
Btw: I read this quick book Threading in C#. It is very good reference if you would like to remind threading in C# and to find some good tips on sync approaches.
P.S. If someone is interested if I woke up at 8am. (See my previous post). I need to say that I failed that attempt. I woke at 12pm.
In this post I will start with some time consuming algorithm, which is very simple and will move to decrease its execution time with using advantage of my two processors.
Time consuming algorithm
For example you have some complex calculations algorithm, which runs on array of dozens of elements. For simplicity let it be list of doubles like below:
All complex calculations that you do are located in class OneThreadAlgorithm. It goes through all array and gets index of the element, which is more closer to value d that you provide inside of method FindBestMatchingIndex.
If you are interested in DistanceProvider, it just returns between two double elements. Take a look on it.
As you see I have some loop before returning value. It is needed to imitate hard calculations. I’m not using Thread.Sleep(), because there are some nuances, that will appear when we will move to multithreading, so I would I like to neglect them.
First change: dividing calculations to sections
As we see algorithm just loops through collection of values and finds some element. To make it going in few threads first we need to accommodate it. The intent of our accommodation is to divide calculations to sections, so we introduce following method
So, what it does is the same that we had previously. Only the difference is that now we start searching for best matching indexes in range starting with index start and finishing with end, also we put result to the BestMatchingElements list. After we went through all sections we can find best matching element only in that list. See that below:
So now it works as well as before, theoretically it is a bit slower, and it does, especially when you divide array to lot of segments (number of segments we define with variable
Second modification: storing task information into one object
When we use multithreading we schedule method which represents public delegate void WaitCallback (Object state). So to accomplish this we create new class FindBestInRangeRequest and use it as an object that passes to changed method:
public void FindBestMatchingIndexInRange(object bestInRangeRequest)
That new class FindBestInRangeRequest encapsulates Start, End, D and other values needed to schedule a threading task. See that class:
As you see we are also passing the ManualResetEvent
object, which has method Set(), with using it we can identify that task execution has finished.
Third modification: Using ThreadPool
We can allocate threads manually, but that operation is very expensive, so it is strongly recommended to use ThreadPool.
So here is how we do use ThreadPool to call FindBestMatchingIndexInRange.
after we have scheduled all ranges we should ensure that all threads has synchronized. We could do this using
Another interesting thing is that saving into BestMatchingElements is not safe, so we use to unsure safe adding.
which is the same to the locking with keyword lock.
Full code base of algorithm
Do you see how our class is cumbersome. So that is why do we call multithreading to be complex and not an easy to implement.
Does this pay off?
Of course, it does. I wrote this example, because I’ve been working on another, a bit more complex thing, but generally I did the same.
Here is output of execution of three variants of algorithm: simple, division to sections, multithreading.
As could bee seen, multithreading variant is much-much faster. It could be even faster if I had more than two processors on my machine.
I heard a lot of the corruption that could be made by the multiple threads when they share same data. And understanding why that happen is not so hard, but I wanted some bright example of it, which will be able to quickly show what is going on.
So here is my example:
As you see I’m using 500 threads. Why? First it is because this ensures that lot of them will be allocated on another processor and second is because the UpdateCount runs “Count = Count + 1” that is quite very trivial and requires about 3 atomic operations, so to increase possibility to run them in concurrent threads I increased their count.
Below is the output:
Here I have code that provides some explanations to the multithreading in .NET. Wrote it to refresh what I know on concurrency.