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

C#-代码处理顺序-奇怪的行为,c#,winforms,C#,Winforms,我有以下按钮单击事件: private void btnRun_Click(object sender, EventArgs e) { label1.Visible = true; if (SelectDatabase()) { if (string.IsNullOrEmpty(txtFolderAddress.Text)) MessageBox.Show("Please selec

我有以下按钮单击事件:

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

                                }
        }


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


谢谢。

您的整个方法当前作为一个阻塞单元运行-添加一个作为解决方案,但实际上您应该在后台线程中执行这种处理,即使用后台工作线程。

代码在绘制用户界面的同一线程上执行。因此,在代码执行时,不会重新绘制UI。按钮单击代码完成后,UI将重新绘制,并且
label1
将以不可见的方式绘制


例如,您可以使用
Task
BackgroundWorker
将代码移动到单独的线程中。但是,您不能直接从其他线程设置UI属性,因此您需要小心地从UI线程设置UI属性,或者注意如何从其他线程更新GUI。

您在UI线程内完成所有操作,这是一个非常糟糕的主意-UI无法更新,对事件等做出反应,直到完成

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

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

  • 不要做任何可能在UI线程中花费大量时间的事情
  • 不要从UI线程以外的任何线程中接触任何UI元素

在代码块完成之前,视图不会更新。因此,我会为递归部分提出一个新的解决方案。

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

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


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

哎哟。Application.DoEvents是一种黑客行为——这段代码不应该在UI线程上执行,而且是一种非常危险的黑客行为。我很高兴你补充了这一澄清;你险些被我投了一票有太多的答案提出了考虑不周的建议,无法使用
应用程序。DoEvents
。如果函数保存表单,请尝试刷新表单,可能会有所帮助<代码>form1.refresh()等待新线程完成的最佳方式是什么?我有另一个方法,它必须等待递归完成。如果我使用一个单独的线程,然后使用while(thread.isalive){}之类的东西,它显然会阻塞线程,直到新线程完成。你推荐什么?谢谢。@Darren:让文件处理代码封送一个对UI线程的调用,调用以后需要继续的任何方法(例如重新启用按钮等)。非常感谢。例如,我只是简单地使用了一些东西:btnRun.Invoke((MethodInvoker)delegate{//Run Method})@达伦:是的,那类事情。就我个人而言,我更喜欢使用
BeginInvoke
,除非您真的需要工作线程来阻止,但这是一个次要问题:)