Saturday, August 21, 2010

C# threads

For the last week or so I've been battling threads in C#. My background at university was largely in embedded programming, so the idea of parallel programming was not one I ventured into often apart from Java and GUI threads. When I did do parallelism, it was generally a quick hack using timers and poorly launched background workers or delegates. In this new program I'm working on however, I am developing a very safety-conscious service with lots of parallel threads, so I've been hitting the C# books virtually to learn my way through it. Here's some notes:

Timers
As I mentioned, I used to develop on GUIs. Moving to a service, you lose a lot of functionality if you are just copying and pasting a class over. One of these that I used to always depend on was the Windows.Forms.Timer. Apparently, when you switch over to a non-GUI program, it won't work. It won't even compile. (side note, I really need to change my AXIS camera control now. This last month of in depth C# programming has shown me the error of my previous ways.)

So I had to change all of my Forms.Timers to System.Threading.Timer. The problem is, it's not just simple swapping. There's no Tick method, there's no start or stop method. You initialise it and it starts running forever... Or does it?

Initialisation is easy. For a one shot timer you can use this, with TimeOut being an integer length of time in milliseconds, and timeOutTimer_Tick being the class that is called on tick.

_timeOutTimer = new Timer(timeOutTimer_Tick, null, TimeOut, TimeOut);

private void timeOutTimer_Tick(object state) {

if(Monitor.TryEnter(_timeOutTimer)) {

// do stuff
}
Monitor.Exit(_timeOutTimer);

}

In the initialisation call it is Timer(delegate, object, int, int). Obviously the delegate is the function to call on tick, the object is the state to be passed into our function (in my case null), the first integer is how long to wait until the first tick is fired (you can have a longer startup period) and the last integer is the tick length.

In the tick function you can see I have a Monitor.TryEnter() and a Monitor.Exit that passes the timer object itself. These calls try to place a lock on the timer object and only if locked willwe be allowed to process. This is very important in threading (it took me a few hours to find out) as it means no other thread can access it while you are working.

Two quick things.
  • For an one-shot timer, use Timeout.Infinite for the last integer
  • You can call _timeOutTimer.change() to change the timer length. It's very similar to the initialisation call.
Parallel Stacks
One of the great things about developing in Visual Studio 2010 is it's support for parallelism. In frustration I stumbled across some great debugging tools (I literally enabled every debugging window to see if there was anything there to help), the greatest being Parallel Stacks.


They let you visualise the parents/children of each thread and all of their current call stacks at once. If there are multiple of any thread, they are encapsulated in each bubble. Neato! You can read more about it here

No comments:

Post a Comment