[C#] 使用 Invoke & BeginInvoke 的元件調用方式,讓程式執行效率更順暢! -JY. MN 軟實力
以往的程式在進行中,需要 UI
元件更新時,往往都是直接調用控制元件進行屬性更新。在多執行緒的專案上,這樣的調用方式是錯誤的。Inovke
與 BeginInvoke 主要功能是在執行緒中使用委派進行調用 UI
控制元件,進行元件屬性的跟動,其中也包含控制元件的數據更新。
程式中使用 ProgressBar (兩個) 、Button (兩個) 控制元件來做簡單的示範:
示範
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace EX_Invoke_BeginInvoke { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public delegate void MyInvoke(ProgressBar pb); private void Update_progressBar1(ProgressBar pb) { // 執行PerformStep()函式 pb.PerformStep(); } private void btn_Invoke_Click(object sender, EventArgs e) { MyInvoke mi = new MyInvoke(Update_progressBar1); // 顯示進度條控制元件 progressBar1.Visible = true; // 設定進度條最小值 progressBar1.Minimum = 1; // 設定進度條最大值 progressBar1.Maximum = 100; // 設定進度條初始值 progressBar1.Value = 1; // 設定進度條每次增加的步長 progressBar1.Step = 1; for (int i = 0; i < 100; i++) { Thread.Sleep(300); this.Invoke(mi, new object[] { progressBar1 }); } } private void btn_BeginInvoke_Click(object sender, EventArgs e) { MyInvoke mi = new MyInvoke(Update_progressBar1); // 顯示進度條控制元件 progressBar1.Visible = true; // 設定進度條最小值 progressBar1.Minimum = 1; // 設定進度條最大值 progressBar1.Maximum = 100; // 設定進度條初始值 progressBar1.Value = 1; // 設定進度條每次增加的步長 progressBar1.Step = 1; for (int i = 0; i < 100; i++) { Thread.Sleep(300); this.BeginInvoke(mi, new object[] { progressBar2 }); } } } }
說明
在範例程式中,先創立一個委派可調用工具。後續創立兩個 Button Click 事件,裡面分別使用 Invoke 與 BeginInvoke 這兩種調用方式:
- Invoke: 程式碼在跑完 this.Invoke(mi, ****) 後會直接進 Update_progressBar1(ProgressBar) 方法內進行 ProgressBar 進度條更新。
- BeginInvoke: 會等到 ButtonClick 跑完後才會進 Update_progressBar1(ProgressBar) 方法進行 ProgressBar 進度條更新。
結論
這兩者的差異在於更新控制元件的時序不同,白話說就是 Invoke
會立即更新,BeginInvoke
會排序更新(比較慢)。這樣做的好處在於預防執行序衝突的狀況產生,往往在大型專案上一些不明錯誤都會發生在這種小地方上,請各位碼農多多注意了!




留言
張貼留言