C# - 代码处理顺序 - 奇怪的行为

时间:2011-04-04 13:38:41

标签: c# winforms

我有以下按钮点击事件:

private void btnRun_Click(object sender, EventArgs e)
    {
        label1.Visible = true;

        if (SelectDatabase())
        {
            if (string.IsNullOrEmpty(txtFolderAddress.Text))
                MessageBox.Show("Please select a folder to begin the search.");
            else
            {

                if (cbRecurse.Checked == false || Directory.GetDirectories(initialDirectory).Length == 0)
                {
                    CheckSingleFolder();
                }
                else
                {
                    CheckSingleFolder();
                    directoryRecurse(initialDirectory);
                }

                                }
        }


    }

实际上,它会执行一些检查,然后启动一些目录递归以查找特定文件。但是,直到目录被递归之后,才会出现使标签可见的第一行代码?有人知道为什么会这样吗?

感谢。

5 个答案:

答案 0 :(得分:8)

你正在做UI线程中的所有事情,这是一个非常糟糕的主意 - 在你完成之前,UI不会更新,对事件做出反应等。

您应该使用后台线程并使用Control.BeginInvoke使用进度等更新UI,或者使用BackgroundWorker

基本上,WinForms中有两条黄金法则(类似于WPF / Silverlight):

  • 不要做任何可能在UI线程中花费大量时间的事情
  • 请勿触摸任何线程其他而不是UI线程
  • 的任何UI元素

答案 1 :(得分:1)

您的整个方法目前作为阻止单元运行 - 添加Application.DoEvents()作为解决方法,但实际上您应该在后台线程中进行此类处理,即使用后台工作程序。

答案 2 :(得分:1)

代码正在绘制用户界面的同一个线程上执行。因此,在代码执行时,您的UI不会被重新绘制。按钮单击代码完成后,将重新绘制UI并隐藏label1

您可以使用例如TaskBackgroundWorker将代码移动到单独的线程中。但是,您无法直接从其他线程设置UI属性,因此您需要小心地从UI线程设置UI属性,或者see this question关于如何从另一个线程更新GUI。

答案 3 :(得分:1)

在代码块完成之前,视图不会更新。所以我会为递归部分提出BackgroundWorker

答案 4 :(得分:1)

解释:标签设置为可见,它是无效的(需要重新绘制)但Windows消息泵在空闲运行之前不会重新绘制。所以你的代码会阻止它。

一个简单的解决方案是在将label1.Update()设置为可见后立即调用它。

更好的解决方案是将耗时的代码移到线程(Backgroundworker)。