Windows Form 加入载入动画
在 Windows Forms 应用程式中加入「载入动画」并不简单:解决「UI 执行绪阻塞」问题。以下是说明、实作步骤及范例程式码。
什么是「UI 执行绪阻塞」?
当一个表单(Form)取得操作焦点时,其他在背景运行的表单将暂停动作。因此,当载入动画出现时,必须另开执行绪在背景中执行接着要显示的新表单,才能让动画持续播放。
主执行绪的控制权问题
这时又产生了一个问题...由于新表单是透过另一个执行绪开启的,当新表单显示时,该执行绪会取得控制权成为主执行绪,而负责动画的执行绪则失去控制权,使得关闭动画的操作无法顺利执行。因此,必须将「关闭动画」的指令交由处理新表单的执行绪来执行。
完整实作流程
借由使用 async / await 关键字,能用最少的程式码完成以上流程。
范例程式 Sample Code
表单及元件配置:
Form1.cs
private async void btnOpenForm2_Click(object sender, EventArgs e)
{
using (var formLoading = new FormLoading())
{
// 在背景执行绪初始化 Form2,完成后关闭动画再显示 Form2
var loadForm2Task = Task.Run(() =>
{
var form2 = new Form2();
formLoading.DialogResult = DialogResult.OK;
form2.ShowDialog();
});
// 以Dialog显示loading form,锁住其他的表单强迫使用者等待
formLoading.ShowDialog();
// 等待 Form2 完成初始化并显示
await loadForm2Task;
}
}
Form2.cs
public Form2()
{
InitializeComponent();
LoadData();
}
private void LoadData()
{
// 模拟载入时间 (非同步等待 5 秒)
Thread.Sleep(5000);
Label lbl = new Label { Text = "loading complete", AutoSize = true };
this.Controls.Add(lbl);
}
FormLoading.cs
public FormLoading()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterParent;
this.FormBorderStyle = FormBorderStyle.None;
}
本文同步发表至我的Blog