Thursday, November 30, 2006

Update GUI controls in multi-threaded WinForm apps in .NET 2.0

.NET 2.0 by default doesn't allow code running in a separate thread to update controls created by the main GUI thread. So if you create a new thread, that thread cannot call Textbox1.Text = "Hello World" for example.

There are two ways around this - set the CheckForIllegalCrossThreadCalls flag to false. This will allow .NET 1.1 controls to work as they did under the 1.1 framework.

The proper way to do it (according to Microsoft) is to create a method to do the control update, then call that method (on the main thread) through a delegate.

Its always easiest to see some code example. In this example, I am hiding/showing the main form from a worker thread.

At the top of my form class I have the following:
delegate void SetFormVisibleCallBack(bool visible);


The actual method to set the Visible flag is:

private void SetFormVisible(bool visible)
{
if (this.InvokeRequired) /*returns true if we are calling the method from a worker thread.*/
{
SetFormVisibleCallBack visCB = new SetFormVisibleCallBack(SetFormVisible);
this.Invoke(visCB, new object[] { visible });
}
else
{
this.Visible = visible;
}
}

If called from a worker thread, SetFormVisible Invoke()'s the main thread to call the SetFormVisible method again. When it does so, this.InvokeRequired will be false, allowing the Visible property to be directly set.

Now, to set the form's Visible property from the main thread or a worker thread, simply call:
this.SetFormVisible(false);


There is an Microsoft Help article on this, but its unnecessarily hard to follow.

Wednesday, November 29, 2006

Sound Detection using C#

I few weeks ago I needed to detect sound through a microphone. What I wanted to do was turn on a computer screen when a sound was heard (talking, clapping etc). After a long google session, all I turned up were several expensive sound detection systems and a piece of VB6 code which sets up the soundcard for sampling using the Win32 API.

Instead of porting all the API code to C#, and having an 'interesting' history with VB6 (who doesn't), I hacked the VB6 code into a dll. This library now provides a list of available recording devices, listens to the microphone and raises an event when the volume is greater than a given threshold. And best of all its easily accessible from .NET code.

Internally, it
  • Grabs a buffer of 8-bit samples from the soundcard. 8-bit means each sample value is 0-256, with 127 being silence.
  • Loops through the buffer, and if there is a value greater than the threshold, raise an event

Get the Detector library (+ source + sample C# application)
Feel free to use it in your own projects. Enjoy!

Monday, November 27, 2006

Hello World!

Welcome to my new blog! It will probably cover a whole lot of different topics, from software development to philosophical musings...