Simon Harriyott

Using BeginInvoke to update the GUI safely between threads

An issue I've had a couple of times recently is updating (for example) a text box on a WinForms GUI. I'm coding away quite happily, and just stick in a

textBoxWeather.Text = "rainy";


or some such thing. This is fine, unless it's run from an event handler. This may be run from a different thread, which makes it unsafe to change something on the GUI. To get round this, the line of code should be put into a method, and be called using BeginInvoke:

delegate void SetWeatherCallback(String weather);


private void SetWeather(String weather)

{

    if (this.InvokeRequired)

    {

        SetWeatherCallback cb = new SetWeatherCallback(SetWeather);

        this.Invoke(cb, new object[] { "rainy"});

    }

    else

    {

        textBoxWeather.Text = weather;

    }

}


When calling this from a different thread, this.InvokeRequired is true, meaning that the thread can't access the GUI directly, so it calls BeginInvoke to call the same method (i.e itself) safely. This time, this.InvokeRequired is false, so the text box is changed directly.

I've needed to do this three or four times recently, and each time I couln't quite remember exactly what it was that I had to do, so I had to look it up. Yesterday I wrote a CodeSmith template to do this, which I've used twice today already. If you'd like a copy of the template, let me know.

[Tags: ]
26 May 2006