---
title: "The 3 ways to create a Thread-Safe GUI with .NET 2.0, with one clear winner."
url: "https://osherove.com/blog/2006/3/1/the-3-ways-to-create-a-thread-safe-gui-with-net-20-with-one.md"
canonical: "https://osherove.com/blog/2006/3/1/the-3-ways-to-create-a-thread-safe-gui-with-net-20-with-one.html"
published: "2006-03-01T02:13:00"
updated: "2006-03-01T02:13:00"
tags: [".Net 2.0"]
author: "Roy Osherove"
description: "With .NET 2.0 and with the new \"anonymous delegates\" feature in C#, doing multi threaded responsive GUIs is now easier. In fact, you get multiple choices on how to accomplish this task. But which choice is the best? and…"
usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)."
license: "https://creativecommons.org/licenses/by/4.0/"
---

# The 3 ways to create a Thread-Safe GUI with .NET 2.0, with one clear winner.

By Roy Osherove March 1, 2006 In [.Net 2.0](https://osherove.com/blog/category/net-2-0)

**Historical article** · Originally published March 1, 2006; technical details may be outdated.

With .NET 2.0 and with the new "anonymous delegates" feature in C#, doing multi threaded responsive GUIs is now easier. In fact, you get multiple choices on how to accomplish this task. But which choice is the best? and what does "best" really mean? more elegant? faster? more readable? all of the above?

Here's a little scenario for you. Assume there is a method that displays a string on the GUI, but may be called by a different thread than the GUI. The method has only a single string parameter. here are three versions of how you can implement this method and keep it thread safe. The last one is my favorite.

First, I'll declare two "generic" delegates. Each one is used in a different version of the method.

 delegate void Func<T>(T t);

private void displayError(string message)
        {
            if (InvokeRequired)
            {
                Func<string> del = displayError;
                Invoke(del, message);
                return;
            }
            errorDisplay.Show(message);
        }

This version uses a generic delegate which takes a string argument, then if Invoke is needed, it "Invokes" the delegate passing in the string argument. Note that passing in the string is not a strongly typed operation and may result in runtime errors if we make a mistake in the parameter order for example. That's why I don't like this version at all. But it's the most commonly used that I've seen, which is why I'm writing this.

---

---

delegate void Func();

        private void displayError1(string message)
        {
            if (InvokeRequired)
            {
                Func del = delegate { displayError1(message); };
                Invoke(del);
                return;
            }
            errorDisplay.Show(message);
        }
        

This version uses a delegate with no parameters, and uses the "delegate" directive to create a delegate that calls the same method with the "message" parameter. Notice how lovely it is to be able to use a local scoped variable such as "message" in out delegate. It makes life much simpler because now all we ever need to do is just use **one delegate signature** for all of our thread-safe GUI work. This version is much better than the previous one because it's type-safe. We can't make a mistake in parameter order or type, or we'll have a build error. But this version is **still** not as elegant as I would like.

---

---

        private void displayError2(string message)
        {
            Func del = delegate
                {
                    errorDisplay.Show(message);
                };
            Invoke(del);
        }

This version uses the delegate directive to actually create the full functionality of our method. Notice that we \*always\* invoke the code in here using the "Invoke" method which is thread-safe, even if this is not required. Also note how much less code we have to write here, and that we always use the same delegate signature to accomplish this. Not only that, in contrast to the other two implementations, we only write the calling code **once inside the delegate, and not another time outside of it which can lead to maintenance problem due to duplication.** This method, to me, is the most elegant and readable. I don't really care about one extra call to the "Invoke" method, since this method is GUI related, and obviously is called after a long operation which was async. 10 nano seconds more or less won't matter one bit. This is the method I'd encourage you to use, even though it seems a bit un-orthodox at first, it is clearly the simplest of the three, with less code, less duplication and more readability.

---

Colorized by: [CarlosAg.CodeColorizer](http://www.carlosag.net/Tools/CodeColorizer/)

Unfortunately, all three methods require you to use C#, since anonymous delegates are not present in VB.NET yet.

Thoughts?

## More in .Net 2.0

[All posts in .Net 2.0](https://osherove.com/blog/category/net-2-0)

- Mar 22, 2006

    ### [Windows Complication Foundation](https://osherove.com/blog/2006/3/22/windows-complication-foundation.html)

- Mar 13, 2006

    ### [Code from DevDays Belgium available: Design for Testability & Smart Client Offline Caching and Synchronization](https://osherove.com/blog/2006/3/13/code-from-devdays-belgium-available-design-for-testability-a.html)

- Feb 6, 2006

    ### [FIX: error message while rebuilding a solution and trying to view a Windows Form in Design view (VS 2005)](https://osherove.com/blog/2006/2/6/fix-error-message-while-rebuilding-a-solution-and-trying-to.html)

- Feb 4, 2006

    ### [.NET 2.0 certification study group in Israel? Your choice.](https://osherove.com/blog/2006/2/4/net-20-certification-study-group-in-israel-your-choice.html)


---

## About the author

**Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery.

### Sites

- [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership.
- [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts.
- [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin.
- [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model.
- [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps.
- [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes).

### Social

- X: https://x.com/royosherove
- LinkedIn: https://www.linkedin.com/in/osherove/

### Contact

- Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7

### License

Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/
