表单加载时的睡眠任务不起作用

Sleep Task on Form load not working

我正在使用以下代码在我的表单加载方法变得可见之前(在显示初始屏幕之后)应用延迟。我已将表单加载定义为 async:

private async void MainForm_Load(object sender, EventArgs e)

这是我在 MainForm_Load 末尾的延迟函数:

Task startTimer = Task.Factory.StartNew(() =>
{
    Thread.Sleep(5000);
});
await startTimer;            
splash.Close();
this.Visible = true;

但是我的延迟功能不起作用,我的初始屏幕立即关闭并且我的表单变得可见。我做错了什么?

更新: 这是我的表单加载代码。但是我再次从中删除了一些块,所以我不会让你头疼:

private async void MainForm_Load(object sender, EventArgs e)
{
    this.Visible = false;
    // Check license
    // Load two user controls
    Splash splash = new Splash();
    splash.Show();
    RefreshPostbagFolder();
    InitiateGeneralSettings();
    InitiateRunSelectFile();
    InitiateRunSelectManualCampaignType();
    InitiateImageList();
    RefreshManageTab();
    RefreshProgramLog();
    RefreshServiceLog();
    await Task.Factory.StartNew(() => { Thread.Sleep(5000); });
    //await startTimer;            
    splash.Close();
    this.Visible = true;
    this.BringToFront();
}

这很有趣,目前我还没有任何解释。我确信 WinForms 的工作原理不仅仅是设置这些属性。但是这个基本示例 确实 重现了这个问题:

private async void Form1_Load(object sender, EventArgs e)
{
    this.Hide();
    await Task.Factory.StartNew(() => { Thread.Sleep(5000); });
    this.Show();
}

单步执行调试器中的代码,实际上 发生的事情并不是没有等待其余代码,而是 Hide()做我们的想法。直到 after Form1_Load 执行后,表单才真正显示出来。由于它是异步执行的,因此用于显示表单的内部组件能够在 await 期间执行。但为时已晚,无法隐藏表格。

这显示了承诺:

private async void Form1_Load(object sender, EventArgs e)
{
    BeginInvoke(new MethodInvoker(delegate
    {
        this.Hide();
    }));
    await Task.Factory.StartNew(() => { Thread.Sleep(5000); });
    this.Show();
}

它所做的是在组件显示表单后调用 Hide()。但是,表格仍会显示几分之一秒。所以并不理想。

我已经 long 时间没有用 WinForms 做任何事了(即便如此我也没有做太多),所以我不确定如何加载没有显示的表格。但这至少涉及到为什么在您的情况下它不是 "awaiting" 的问题。它 等待,但是 等待是表单最初显示的时间。所以隐藏形式before那一点是没有效果的。

您的主表单会在 Application.Run here 中自动显示并激活,请注意 applicationContext.MainForm.Visible = true

一旦执行点 returns 从 Form.Load 事件处理程序到触发事件的代码(在您的情况下,它就是它命中内部的 await 的地方,它就会变得可见MainForm_Load), 所以异步部分不影响它的可见性。

为避免闪烁,您可以先将表单显示为最小化且不显示任务栏图标,如下所示:

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var form = new Form { 
                WindowState = FormWindowState.Minimized, 
                ShowInTaskbar = false };

            form.Shown += delegate 
            {
                Debug.Print("form.Shown");
            };

            form.Load += async delegate
            {
                Debug.Print("form.Load");

                var splashForm = new Form { Text = "Splash!" };
                splashForm.ShowInTaskbar = false;
                splashForm.Show();

                await Task.Delay(5000);

                splashForm.Hide();

                form.WindowState = FormWindowState.Normal;
                form.ShowInTaskbar = true;

                form.Show();
            };

            Application.Run(form);
        }
    }
}

您可以先在 VS 表单设计器或 MainForm 的构造函数中设置 Form.WindowStateForm.ShowInTaskbar,而不是修改 Program.Main

附带说明,使用 Task.Delay 而不是用 Task.RunTask.Factory.StartNew 包装的 Thread.Sleep