poiasd
poiasd

Reputation: 169

Code in button click c# happens after the function finishes

I have some simple C# code that is triggered on a Button Press. The button press first clears some ListBoxes, then changes the text of a label, and then calls a function.

private void button1_Click(object sender, EventArgs e)
{
    listBox1.Items.Clear();
    listBox2.Items.Clear();
    listBox3.Items.Clear();
    listBox4.Items.Clear();
    label5.Text = "Getting links...";
    process(url);
    label5.Text = "Finished";
}

But the Lists are cleared and the label is changed after process() is finished executing. This ruins the purpose as I'm changing the label so that the user is aware that some action is taking place. How can I make the initial label change before the function process() finishes?

Upvotes: 1

Views: 1065

Answers (4)

PiotrWolkowski
PiotrWolkowski

Reputation: 8782

You can use async keyword. Only when accessing the UI from different thread you have to use the Invoke

private async void button1_Click(object sender, EventArgs e)
{
    await Task.Run(
        () =>
            {
                this.Invoke((MethodInvoker)delegate
                    {
                        listBox1.Items.Clear();
                        listBox2.Items.Clear();
                        listBox3.Items.Clear();
                        listBox4.Items.Clear();
                        myLabel.Text = "Getting links...";
                    });
            });

    this.process(url);

    await Task.Run(
        () =>
            {
                this.Invoke((MethodInvoker)delegate { myLabel.Text = "Finished"; });
            });
}

Upvotes: 2

Andrey Korneyev
Andrey Korneyev

Reputation: 26876

If your process method is long-running, it can cause UI freezing and prevent UI from redrawing - that's why you don't see your label text immediate update.

Simpliest way to achieve your goal - is call label5.Refresh() right after label5.Text = "Getting links...";, this will immediately cause invalidation and redrawing of label.

Or even you can call this.Refresh() if more than one control should be updated - this will update whole usercontrol or form owns your controls.

But note - if your process method runs a very long time (more than a 2-3 seconds for example) - you should consider doing it asyncroniously in thread separate from UI. It is considered as "good style" because it will not cause UI freezing.

Upvotes: 2

F2K
F2K

Reputation: 481

What about using a Task to run process(url) in a "thread" separated from GUI? In this way GUI will stay responsive to the user ang got "refreshed", then, when your task ends, you just have to update GUI label.

When you have ops that must take a bit of time, you should always separate them from GUI. My two cents.

Upvotes: 1

Zohar Peled
Zohar Peled

Reputation: 82504

You have 2 options. either use a different thread to run process(url), or add before it Application.DoEvents().

Upvotes: 0

Related Questions