简体   繁体   中英

Change label text and start threads in the same void

I have a big problem and hope you guys can help me...

I need to start a Thread called ListenOnSocket , no problem so far..

Thread ListenOnSocket = new Thread(newThreadStart(Form1.ListenOnSocket));
ListenOnSocket.Start();

But when I want to change the label from within ListenOnSocket , I get an object reference is required for the non-static field, method or property.

So normally you would passe the label on by doing this

 public static void ListenOnSocket(Label lblstatus)
 {
     //i want to change the label from here.
     lblstatus.text = "Hello";
 }

but then I get

No overload for ListenOnSocket matches delegate System.Threading.Threadstart in my threadstart.

Can anyone please help, I am really stuck, sorry if there is not much to go on I am quite new to C#.

You can use Lambda Expression to pass parameter.

Thread ListenOnSocket = new Thread( () => { Form1.ListenOnSocket(yourParameter); } );
ListenOnSocket.Start();

But you will get the CrossThreadException when the ListenOnSocket method execute. So you need to use BeginInvoke to set label text.

So search the CrossThreadException and why you will get it.

Note: I do not write the sample code for this, because searching is more beneficial.

You need to marshal this back to the UI thread:

public static void ListenOnSocket(Label lblstatus)
{
    this.BeginInvoke(new Action(() => 
    {
        //i want to change the label from here.
        lblstatus.text = "Hello";
    });
}

It looks like you might actually want a ParameterizedThreadStart here. You would pass the Label in as its parameter. Control changes also need to be performed on the UI thread.

    public void DoSomething()
    {
        // Actually a ParameterizedThreadStart, but you don't need to state this explicitly
        //var listenOnSocket = new Thread(new ParameterizedThreadStart(ListenOnSocket));
        var listenOnSocket = new Thread(ListenOnSocket);

        // Pass the label as the ParameterizedThreadStart parameter
        // TestLabel is a label within the form
        listenOnSocket.Start(TestLabel);
    }

    private void ListenOnSocket(object statusLabelObject) // Parameter must be of type Object
    {
        var statusLabel = statusLabelObject as Label;
        if (statusLabel == null)
            throw new ArgumentException(@"Parameter must be of type Label", "statusLabelObject");

        // Changes to controls must be performed on the UI thread.
        BeginInvoke((Action)(() => statusLabel.Text = @"text"));
    }

They key gotcha here is it's not valid to update a UI element (like a label) from a background thread.

If you have a long running task then you probably don't want to run that on the UI thread as it will block.

Assuming that you're creating a thread because you have something that runs for too long to run on the UI thread, it might be worth looking into way of marshalling calls from background threads onto the UI thread.

For more information on how to do this see How to update the GUI from another thread in C#? if you're looking to update the status from a long running task, you might want to look into background worker: MSDN: How to Use Background Worker which is a helper class designed to help with long running background tasks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM