Showing posts with label parallel stacks. Show all posts
Showing posts with label parallel stacks. Show all posts

Wednesday, December 15, 2010

C# GUI Hangs on Invoke

If you've ever tried doing any advanced work using GUIs in C#, you'll be friends/enemies with the good old fashioned Cross-thread operation not valid exceptions. GUI controls run on their own thread and any other thread can't access them.

The great work around is to invoke the control. For instance, I use the following method to update a richTextBox control from any thread I happen to be in:

public delegate void StringParameterDelegate(string value);

public void UpdateRichTextBoxStatus(string value)

{

if (InvokeRequired)

{

// We're not in the UI thread, so we need to call Invoke

Invoke(new StringParameterDelegate(UpdateRichTextBoxStatus), new object[] { value });

return;

}

// Must be on the UI thread if we've got this far

richTextBoxStatus.Text = value + richTextBoxStatus.Text;

}



It checks to see if the control needs invoking (to avoid the cross-thread exception). If it does, it will reursively call itself again using a delegate and then update the richTextBox.

This worked fine and dandy most of the time. However, I had one condition where different invocations were happening at the same time, on different controls, but being invoked from an external, managed DLL. What happened is the invoke occured, but then the whole program hung on a call to the DLL.

Further investigation (god bless the parallel stacks threading debugging view) showed that one of the invocations went into a sleep state, waiting for the other invocation to finish. The Invoke call itself is synchronous, so the next invoke call was waiting for the original to finish. And hence the program just hung there. Waiting... waiting... never finishing.

Well there's an easy workaround for this. Instead of calling Invoke, call BeginInvoke! This makes the call asynchronous. The function thus becomes:

public delegate void StringParameterDelegate(string value);

public void UpdateRichTextBoxStatus(string value)

{

if (InvokeRequired)

{

// We're not in the UI thread, so we need to call BeginInvoke

BeginInvoke(new StringParameterDelegate(UpdateRichTextBoxStatus), new object[] { value });

return;

}

// Must be on the UI thread if we've got this far

richTextBoxStatus.Text = value + richTextBoxStatus.Text;

}

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