WinForms 非同步必學:用 async/await 擺脫 UI 卡頓
Copyright Notice: This article is an original work licensed under the CC 4.0 BY-NC-ND license.
If you wish to repost this article, please include the original source link and this copyright notice.
Source link: https://v2know.com/article/1149
背景
在按鈕事件中若直接執行同步 I/O(如 ToList()
)或耗時計算,會鎖死 UI,畫面無法拖曳、重繪,甚至被系統標示為「(無回應)」。
1. await
的核心作用
-
分段執行
遇到await
時,方法會將後續程式拆成 callback,先把控制權還給 WinForms 的訊息迴圈。 -
保證順序
有await
,後續程式碼僅在被 await 的Task
完成後才執行;若忽略await
,便可能「fire-and-forget」。 -
不一定開新執行緒
非同步 I/O(如ToListAsync()
)本身即不阻塞;若需背景 CPU 密集,可採await Task.Run(...)
。
2. UI 不鎖死的好處
-
持續回應:視窗可拖曳、最小化、重繪,不會顯示「無回應」。
-
事件排隊:使用者在 await 期間點擊其他按鈕,該事件入隊,待當前非同步完成並恢復後再執行。
-
進度與取消:可在等待時更新進度條或實作「取消」機制,提升使用者體驗。
3. 簡易範例
private async void btnProcess_Click(object sender, EventArgs e)
{
CollectProcessInput();
// 非同步取資料,UI 不鎖死
var list = await context.Entities.ToListAsync();
// 確保資料拿到後才執行
UpdateUI(list);
}
4. 實作建議
-
I/O 密集:優先使用框架提供的非同步 API。
-
CPU 密集:包裝於
Task.Run(...)
;並以await
等待結果。 -
落實 await:確保所有需要等待的非同步呼叫前皆加
await
,避免執行順序錯亂。
透過 async/await
,你可以用近似同步的程式流程,確保順序執行非同步邏輯,同時維持 WinForms UI 的流暢與回應性。
This article was last edited at