在 Windows Forms 應用程式中加入「載入動畫」並不簡單:解決「UI 執行緒阻塞」問題。
以下是說明、實作步驟及範例程式碼。
什麼是「UI 執行緒阻塞」?
當一個表單(Form)取得操作焦點時,其他在背景運行的表單將暫停動作。
因此,當載入動畫出現時,必須另開執行緒在背景中執行接著要顯示的新表單,才能讓動畫持續播放。
主執行緒的控制權問題
這時又產生了一個問題…
由於新表單是透過另一個執行緒開啟的,當新表單顯示時,該執行緒會取得控制權成為主執行緒,而負責動畫的執行緒則失去控制權,使得關閉動畫的操作無法順利執行。
因此,必須將「關閉動畫」的指令交由處理新表單的執行緒來執行。
完整實作流程
- 以對話框的形式顯示載入動畫表單,鎖住其他表單並強制使用者等待。
- 在背景執行緒中初始化新表單,然後關閉動畫並顯示新表單。
- 等待背景執行緒完成操作。
藉由使用 async / await 關鍵字,能用最少的程式碼完成以上流程。
範例程式
表單及元件配置
- 建立 3 張 Windows Form:Form1、Form2及FormLoading。
- 在 FormLoading 表單中加入一個 PictureBox 元件,放入 loading.gif 作為載入動畫(GIF 來源:GIFER 網站:https://gifer.com/en/ZKZg)。
- 在 Form1 放置 1 個 button,name 屬性為「btnOpenForm2」, 顯示文字是「Open Form2」。
- Form2 放置 1 個 Lable 元件顯示文字「load complete」,並在 Form2 初始化時等待 5 秒模擬載入延遲。
- 在 btnOpenForm2 的 Click 事件中,加入程式碼以背景執行緒開啟新表單,並控制動畫的關閉與新表單的顯示。
Form1.cs
C#
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
C#
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
C#
public FormLoading()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterParent;
this.FormBorderStyle = FormBorderStyle.None;
}
最後更新日期:2024-11-24
發佈留言