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

Saturday, August 14, 2010

Windows forms styles in C#

Yesterday I was writing a nice little MDI form, and noticed something. My forms look like they were from the 80s. With blocked off group boxes instead of rounded and buttons from 3.1 days instead of the XP style they were supposed to be. On compilation and at runtime, they'd look nothing like they did in the designer.

So there were 2 ways you can get around this. Number 1 is a bit more effort, but it involves making a .exe.manifest file with the same name as your executable. In this manifest file you have some XML (http://www.dotnet247.com/247reference/msgs/15/79151.aspx, or http://www.codeproject.com/KB/cs/xpstyleui.aspx) which dictates how the controls appear. Then you have to change the "FlatStyle" property of each supported control to System.

That's great, it worked well, but it was fucking complicated.

Number 2 is much better. Call Application.EnableVisualStyles() before you launch the form. In my case, I called it before the parent MDI container was launched, and it fixed every internal form as well.

        [STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
And no having to change each control's style separately.