表单加载时的睡眠任务不起作用
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.WindowState
和 Form.ShowInTaskbar
,而不是修改 Program.Main
。
附带说明,使用 Task.Delay
而不是用 Task.Run
或 Task.Factory.StartNew
包装的 Thread.Sleep
。
我正在使用以下代码在我的表单加载方法变得可见之前(在显示初始屏幕之后)应用延迟。我已将表单加载定义为 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.WindowState
和 Form.ShowInTaskbar
,而不是修改 Program.Main
。
附带说明,使用 Task.Delay
而不是用 Task.Run
或 Task.Factory.StartNew
包装的 Thread.Sleep
。