Code Snippets

A few code snippets below are a “quick’n’dirty”. Please use with caution at your own risk.

Updating UI from Another Thread

Since not so long ago, your C# code will throw an exception if you attempt to update WinForm UI from a worker thread. The exception can take a couple of different forms, but typically looks something like:

Cross-thread operation not valid: Control ” accessed from a thread other than the thread it was created on

So in a situation where you have, say, a button that starts a thread that performs a computation AND you need to update a UI element with each iteration of the computation, you will now have to jump through some hoops.

The correct way to do this is to write a method that will check whether it is called from a ‘safe’ context by checking ‘InvokeRequired’ property of the control you are looking to update, and do the right thing.. Microsoft suggests a pattern like this:

private void SetText(string text)
{
    // InvokeRequired required compares the thread ID of the
    // calling thread to the thread ID of the creating thread.
    // If these threads are different, it returns true.
    if (this.textBox1.InvokeRequired)
    {    
        SetTextCallback d = new SetTextCallback(SetText);
        this.Invoke(d, new object[] { text });
    }
    else
    {
        this.textBox1.Text = text;
    }
}

The pain of this is that now you need to write a method for each control, or a type of control (e.g. TextBox), or have a generic method that gets control, property name, value and then uses reflection to perform setProperty, which may be fine.. But sometimes, you *know* you are in another thread and you just want the damn property updated without hassle. So, if your thread function is in the context of your WinForm class, you can do this in your thread function:

this.Invoke((MethodInvoker)delegate
{
   textBox1.Text = "Enough Already";   
});

Inline Thread Functions – quickest and easiest way to create a thread

This actually brings me to another point – thread functions. Typically they’re nice and stuff, but if you implement one you may have to write comments, add lines of unnecessary code to your file, etc. Sometimes you just want to get job done (take it from me ;-)). So expanding on example above, say we have a button and the onclick event handler function that will start a thread, which will update some UI control. Here’s a quick’n’dirty, courtesy of LINQ:

private void uiButton_Click(object sender, EventArgs e)
{
    Thread workerThread = new Thread(() =>
    {
        for (int i = 0; i < 100; i++)
        {
            this.Invoke((MethodInvoker)delegate
            {
                textBox1.Text = i.ToString();
            });
        }
    });
    workerThread.Start();
}
&#91;/csharp&#93;

Ok, so that's that.

<strong>Inline Event Handlers</strong>

But what's this with having an OnClick event handler function?! Nay, I Say. Lets inline that too:

[csharp]
private MyForm()
{
    InitializeComponent();
    Button myButton = new Button();
    myButton.Text = "Click Me";
    myButton.Click += delegate(object o, EventArgs e)
    {
        Thread workerThread = new Thread(() =>
        {
            for (int i = 0; i < 100; i++)
            {
                this.Invoke((MethodInvoker)delegate
                {
                    textBox1.Text = i.ToString();
                });
            }
        });
        workerThread.Start();
    };
    this.Controls.Add(myButton);
}
&#91;/csharp&#93;

So, by now, you probably see where I am going with this, and are rapidly clicking on the 'Back' button of your browser. That's probably a good call. Really, learning functional programming was all for not, when you can do things like this. I say <em>void main()</em> should really be the only function you need ;-).

Last one..

Sometimes (never) it's safe to assume that your input will always be in a correct format. So say you are reading a comma-separated value string from a file and want to convert it to an array of doubles - make it a one-liner:

[csharp]
double[] inputCollection = inputString.Split(new char[] { ',' }, 
   StringSplitOptions.RemoveEmptyEntries).Select(x => double.Parse(x)).ToArray();

Cheers!