Tim Van Wassenhove

Passionate geek, interested in Technology. Proud father of two

21 Jan 2007

About Thread-Safe GUI...

If you’re writing windows applications you’ll most certainly recognize the following piece of code

private delegate void UpdateIntResultDelegate(int result);

private void UpdateIntResult(int result)
{
	if (this.labelIntResult.InvokeRequired)
		this.labelIntResult.Invoke(new UpdateIntResultDelegate(this.UpdateIntResult), result);
	else
		this.myDataSource.IntResult = result;
}

private delegate void UpdateStringResultDelegate(string result);

private void UpdateStringResult(string result)
{
	if (this.labelStringResult.InvokeRequired)
		this.labelStringResult.Invoke(new UpdateStringResultDelegate(this.UpdateStringResult), result);
	else
		this.myDataSource.StringResult = result;
}

Today i was fed up with defining all these Delegates.. So i decided to define a generic delegate instead

delegate void Delegate<t>(T t);

And now i can reuse this Delegate for my two update methods

private void UpdateIntResult(int result)
{
	if (this.labelIntResult.InvokeRequired)
		this.labelIntResult.Invoke(new Delegate<int>(this.UpdateIntResult), result);
	else
		this.myDataSource.IntResult = result;
}

private void UpdateStringResult(string result)
{
	if (this.labelStringResult.InvokeRequired)
		this.labelStringResult.Invoke(new Delegate<string>(this.UpdateStringResult), result);
	else
		this.myDataSource.StringResult = result;
}

Apparently (and not surprisingly) i’m not the first to come up with this idea, a little websearch for ‘Generic Delegate’ learned me that Roy Osherove blogged about it in: The 3 ways to create a Thread-Safe GUI with .NET 2.0, with one clear winner. After reading the article i decided to take the following approach (The call to UpdateIntResult is type-safe, it only calls Invoke when it’s required and no duplication)

void UpdateIntResult(int result)
{
	if (this.labelIntResult.InvokeRequired)
	{
		this.labelIntResult.Invoke(new MethodInvoker(delegate { this.UpdateIntResult(result); }));
	}
	else
	{
		this.myDataSource.IntResult = result;
	}
}