按钮单击c#中的代码在函数完成后发生

时间:2015-04-01 11:45:05

标签: c# multithreading winforms

我有一些简单的C#代码,它们是在按下按钮时触发的。按下按钮首先清除一些ListBox,然后更改标签的文本,然后调用一个函数。

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";
}

但清除列表并在process()执行完毕后更改标签。当我改变标签以便用户意识到某些动作正在发生时,这就破坏了目的。如何在函数process()完成之前更改初始标签?

4 个答案:

答案 0 :(得分:2)

如果您的process方法长时间运行,可能会导致用户界面冻结并阻止重新绘制用户界面 - 这就是您没有看到标签文字立即更新的原因。

实现目标的最简单方法是在label5.Refresh()之后立即调用label5.Text = "Getting links...";,这将立即导致无效和重新绘制标签。

如果要更新多个控件,甚至可以调用this.Refresh() - 这将更新整个用户控件或窗体拥有您的控件。

但请注意 - 如果您的process方法运行非常很长时间(例如超过2-3秒) - 您应该考虑在与UI分开的线程中异步执行此操作。它被认为是"良好的风格"因为它不会导致UI冻结。

答案 1 :(得分:2)

您可以使用async关键字。只有从不同的线程访问UI时,您才必须使用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"; });
            });
}

答案 2 :(得分:1)

如何使用Task在"线程中运行process(url)"与GUI分开? 通过这种方式,GUI将保持对用户的响应状态"刷新"然后,当您的任务结束时,您只需更新GUI标签。

如果您的操作必须花费一些时间,则应始终将它们与GUI分开。我的两分钱。

答案 3 :(得分:0)

您有2个选项。要么使用其他线程来运行process(url),要么在Application.DoEvents()之前添加。