Click here to Skip to main content
15,883,705 members
Articles / Programming Languages / C#
Article

A thread-safe ToolStripStatusLabel control

Rate me:
Please Sign up or sign in to vote.
3.88/5 (7 votes)
6 Jul 20073 min read 77.1K   1.3K   32   15
This article demonstrates how to extend a ToolStripStatusLabel so that it can be updated from another thread

Introduction

Recently, I had the known problem of setting the Text value of a ToolStripStatusLabel control from a thread other than the one that was handling it. This basically can happen when you fire an event from an independent thread method and want to display a message in the client application. The usual way to deal with this is to use the Invoke method of the control to delegate the operation so that it is thread-safe. Unfortunately, ToolStripStatusLabel doesn't have such a method. I searched awhile on the internet to see if someone had a solution to this problem, but I couldn't find any satisfying one.

So, I searched by myself for a solution thinking that Microsoft had surely thought about this. The solution is in the StatusStrip control that contains all of the ToolStrip controls. This class has the InvokeRequired and Invoke methods that are necessary to delegate the call on the right thread. I came out with two solutions, both of which work.

Extending the StatusStrip control

The first solution consists of adding a method to the StatusStrip control to safely set the Text property of the ToolStripStatusLabel it contains. The code to achieve this is given below.

public void SafeSetText(ToolStripLabel toolStripLabel, string text)
{
    if (InvokeRequired)
    {
        SetText setTextDel = 
            delegate(ToolStripLabel toolStrip, string textVal)
        {
            foreach (ToolStripItem item in base.Items)
            {
                if (item == toolStrip)
                {
                    item.Text = textVal;
                }
            }
        };

        try
        {
            Invoke(setTextDel, new object[] 
            { 
                toolStripLabel, text 
            });
        }
        catch
        {
        }
    }
    else
    {
        foreach (ToolStripItem item in base.Items)
        {
            if (item == toolStripLabel)
            {
                item.Text = text;
            }
        }
    }
}

The idea is quite simple. As there is no Invoke method in ToolStripStatusLabel, I use the one of StatusStrip and find on which item I must apply the Text change. The drawback of this technique is that I cannot directly call the Text property of ToolStripStatusLabel and so this property remains unsafe. However, this solution works.

Extending the ToolStripStatusLabel control

The second solution satisfies me better. I override the Text property of ToolStripStatusLabel and make it totally safe so that it is no longer possible to call the original Text property. I think this solution is more elegant and it can be used with other ToolStrip items of a StatusStrip. The code of this solution is given below.

public override string Text
{
    get
    {
        // Make sure that the container is already built
        if ((base.Parent != null) &&        
            (base.Parent.InvokeRequired))   // Is Invoke required?
        {
            GetString getTextDel = delegate()
            {
                return base.Text;
            };
            string text = String.Empty;
            try
            {
                // Invoke the SetText operation from the 
                // Parent of the ToolStripStatusLabel
                text = (string)base.Parent.Invoke(getTextDel, null);
            }
            catch
            {
            }
            return text;
        }
        else
        {
            return base.Text;
        }
    }    
    set
    {
        // Get from the container if Invoke is required
        // Make sure that the container is already built
        if ((base.Parent != null) &&       
            (base.Parent.InvokeRequired))   // Is Invoke required?     
        {
            SetText setTextDel = delegate(string text)
            {        
                base.Text = text;
            };

            try
            {
                // Invoke the SetText operation from the
                // Parent of the ToolStripStatusLabel
                base.Parent.Invoke(setTextDel, new object[] { value });
            }

            catch
            {
            }
        }
        else
        base.Text = value;
    }
}

As you can see in the code, this solution is more straightforward and doesn't need a separate method to set the Text property. The trick is to get the Parent of the ToolStrip item and call the Invoke method with the delegate to set the Text property. The only drawback I found to this method is that you cannot use SafeToolStripStatusLabel from the designer and must modify the code generated by the designer. However, there may be a way to tell the designer to use our SafeToolStripStatusLabel when we add it to the StatusStrip control.

Demo application

In order to demonstrate both methods, I built a simple demo application that can fire one event displayed with the SafeStatusStrip control and one event displayed with the SafeToolStripLabel control. This application uses a thread that waits to send either one event or the other when a button is pressed. The event handlers display a message in the status bar using one of the two methods described previously.

Screenshot - Safetoolstrip1.jpg

Screenshot - Safetoolstrip2.jpg

Points of interest

This code can be used for any ToolStrip control that you might use in a StatusStrip container. You can use it freely in your application by building a component DLL that will contain all your safe controls.

History

  • 6 July, 2007 -- Original version posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Connect In Private
Singapore Singapore
Software Architect, COM, .NET and Smartcard based security specialist.

I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I preferred digital to analog.

I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.

For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when things don't go right!

After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small computers!
I've been back into business to design the licensing system for the enterprise solution for Consistel using a .NET smart card (yes they can run .NET CLR!)

I'm currently designing a micro-payment solution using the NXP DESFire EV1 with the ACSO6 SAM of ACS. I can then add a full proficient expertise on those systems and NFC payments.
This technology being under strict NDA by NXP I cannot publish any related article about it, however I can provide professional consulting for it.

You can contact me for professional matter by using the forum or via my LinkedIn profile.

Comments and Discussions

 
QuestionConverting to VB Pin
Kestrel_rob5-Feb-09 4:08
Kestrel_rob5-Feb-09 4:08 
AnswerRe: Converting to VB Pin
orouit12-Feb-09 21:44
professionalorouit12-Feb-09 21:44 
Hi Rob,

This code is pure C#, not using any interop trick so conversion to VB should be straight forward.

You can take the C# syntax and directly translate it to VB syntax. If something is not working I need more detail!

Olivier

Software Architect, COM, .NET and Smartcard specialist.

GeneralRe: Converting to VB [modified] Pin
Kestrel_rob12-Feb-09 22:18
Kestrel_rob12-Feb-09 22:18 
AnswerRe: Converting to VB Pin
Georg Kohler7-Mar-09 17:02
Georg Kohler7-Mar-09 17:02 
Generalfound a new way Pin
Pr@teek B@h!17-Nov-08 10:04
Pr@teek B@h!17-Nov-08 10:04 
Generalthanks for your idea,I had done this Pin
wangkuang522-Apr-08 18:55
wangkuang522-Apr-08 18:55 
Generalthanks for your idea,I had done this Pin
wangkuang522-Apr-08 18:55
wangkuang522-Apr-08 18:55 
GeneralMore ideas Pin
jsakhtar16-Jul-07 20:37
jsakhtar16-Jul-07 20:37 
GeneralSuggestions Pin
Richard Deeming10-Jul-07 9:35
mveRichard Deeming10-Jul-07 9:35 
GeneralRe: Suggestions ->Thks Pin
orouit11-Jul-07 4:44
professionalorouit11-Jul-07 4:44 
GeneralPossible hole... Pin
Andrew Smith7-Jul-07 16:58
Andrew Smith7-Jul-07 16:58 
GeneralRe: Possible hole... Pin
orouit9-Jul-07 1:54
professionalorouit9-Jul-07 1:54 
General"Unfortunately, ToolStripStatusLabel doesn't have such a method. I searched awhile on the internet to see if someone had a solution to this problem, but I couldn't find any satisfying one." Pin
The_Mega_ZZTer6-Jul-07 18:45
The_Mega_ZZTer6-Jul-07 18:45 
AnswerRe: "Unfortunately, ToolStripStatusLabel doesn't have such a method. I searched awhile on the internet to see if someone had a solution to this problem, but I couldn't find any satisfying one." Pin
orouit9-Jul-07 1:57
professionalorouit9-Jul-07 1:57 
GeneralGot my 5 Pin
Marc Leger6-Jul-07 17:40
Marc Leger6-Jul-07 17:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.