×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Updating a label from a background process

Updating a label from a background process

Updating a label from a background process

(OP)
I have a module that is doing several things. As each thing is started I want to update a label on the main form with some text.

Doing this in vb.net is absolutely no problem. For some reason, however, C# doesn't work the same way.

Developer forums have said to do a form Update() or an Application.DoEvents() after updating it.

Well I have gone even further than that. I have a public method on my form that looks like this:

public void updateStatusDisplay ( string strMessage )
{
lblPleaseWait.Text = strMessage;

this.Update ();
Application.DoEvents();
}

Then in the module that is performing the processes:

frmRptSel_AcctMgrAvg newReport = new frmRptSel_AcctMgrAvg(myCodeTables);

newReport.updateStatusDisplay ( "Report: Pending Inventory" );

The updateStatusDisplay method is being called (I set a breakpoint in it), but the display doesn't update. What the heck is going on???

Why did Microsoft make the behaviour of C# be so different than vb.net in this? In VB, all I have to do in the module is: frmRptSel_AcctMgrAvg.lblPleaseWait.Text = "new text" and the form is updated and you can see it change. I even do something like this utilizing a progress bar in VB the same way. All I have to do is: frmRptSel_AcctMgrAvg.progressBar1.PerformStep()

Thanks in advance,

Jerry Scannell

RE: Updating a label from a background process

.NET does not like updating controls from a different thread than the one it was created on.

You need to check the InvokeRequired field of the control you are updating, and if it is true use the control's Invoke method to call a delegate that will then update the control.

I found a nice little gem somewhere online that makes this really easy for me via an extension method.

CODE

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
    if (control.InvokeRequired) control.Invoke(action);
    else action();
} 
Then to call it via your example:

CODE

public void updateStatusDisplay ( string strMessage )
{
    lblPleaseWait.InvokeIfRequired(() =>
    {
        lblPleaseWait.Text = strMessage;
    });
} 
Of course this assumes you are using a version of the .NET framework that supports extension methods, and inline delegates.

RE: Updating a label from a background process

(OP)
The control that I am attempting to update (lblPleaseWait) doesn't have a property called InvokeRequired, so I don't know what to do with your example.

Also, the code you provided:

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
if (control.InvokeRequired) control.Invoke(action);
else action();
}


What am I supposed to use for "this Control control" and "MethodInvoker action"?

Thanks in advance,

Jerry Scannell

RE: Updating a label from a background process

What version of the .NET Framework are you using? Is lblPleaseWait a System.Windows.Forms.Label?

For access to the Control and MethodInvoker types, you need to be using the namespace: System.Windows.Forms.

The "this" is what makes that function an extension of Control - this requires the .NET framework >= 3.5.

The InvokeIfRequired function should be placed in a static class:

CODE

public static class Extensions
    {
        public static void InvokeIfRequired(this Control control, MethodInvoker action)
        {
            if (control.InvokeRequired) control.Invoke(action);
            else action();
        }
    } 

Pretty much all controls placed on a form (Labels, and even the form itself) are all derived from the Control class. As such the InvokeRequired property is available on all controls, along with the Invoke method. If the answer to the lblPleaseWait is yes, then it does indeed have the InvokeRequired property. If it's no... we'll see, it should still derive from Control and therefore inherit the property - unless it was purposefully hidden.

You can also accomplish this in .NET Framework 2 or 3 like this:

CODE

public void updateStatusDisplay (string strMessage)
{
    if (lblPleaseWait.InvokeRequired)
    {
        lblPleaseWait.Invoke(new MethodInvoker(() =>
        {
            updateStatusDisplay(strMessage);
        }));
    }
    else
    {
        lblPleaseWait.Text = strMessage;
    }
} 

RE: Updating a label from a background process

(OP)
I'm using .net 3.5

It is a standard win form label.

If I load and run a class from within a form, why can't I reference any of the controls on that form from within the class?

Do I have to create a constructor that passes in the main form (e.g. abc def = new abc(this); and then save 'this' as a frmMain type in the module?

Thanks in advance,

Jerry Scannell

RE: Updating a label from a background process

That would be correct. Scope prevents that from happening.

CODE

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
}
public class MyClass
{
    //this class has to have the form passed to it
    private Form1 theForm;
    public MyClass(Form1 f)
    {
        theForm = f;
    }

    public doAction()
    {
        theForm.lblPleaseWait.Text = "test";
    }
} 
That would give your class access to the PUBLIC members of your form, but I believe by default most controls have their modifier set to PRIVATE. You would need to change the Modifiers property of your label to something that would permit that access.

RE: Updating a label from a background process

(OP)
At is exactly what I just did and it works perfectly. I thought of it and implemented it as soon as I posted it.

Jerry Scannell

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close