從目前已經在項目中工作將近一個月來的情況來看,凡是費時的操作,基本上都要用到多線程的等待窗體、進度提示窗體等實時顯示動態的進度信息。而如果直接在主線程的窗體上實時更新信息,就會造成更新太快或者太慢而出現的進程假死現象。為了緩解這些情況,本文就參考一些文章,把他們的智慧總結於此。希望對大家有所幫助。
一、多線程中創建等待窗體
在winform程序開發中,計算機經常會執行一些比較耗時的任務,如大量數據的查詢操作、較為復雜的業務處理等,這些任務往往需要耗時幾秒到幾十秒鍾的時間,在這些任務執行期間winform程序窗體不再響應任何鼠標和鍵盤事件,出現假死狀態,用戶體驗很差。
一個比較好的解決辦法是,在這些任務執行期間在界面前端顯示一個等待窗體,告訴用戶任務正在執行中。
1.1 開發等待窗體
窗體中有一個PictureBox控件和兩個Lable控件,PictureBox控件的Image屬性為一張動態圖片。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; using NavManager.Common; namespace NavManager.Utils { public partial class WaitForm : Form { public WaitForm() { InitializeComponent(); SetText(""); } private delegate void SetTextHandler(string text); public void SetText(string text) { if (this.label2.InvokeRequired) { this.Invoke(new SetTextHandler(SetText), text); } else { this.label2.Text = text; } } } }
1.2 提供訪問等待窗體的接口
編寫類WaitFormService

using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Windows.Forms; namespace NavManager.Utils { /// <summary> /// Using Singleton Design Pattern /// </summary> public class WaitFormService { public static void CreateWaitForm() { WaitFormService.Instance.CreateForm(); } public static void CloseWaitForm() { WaitFormService.Instance.CloseForm(); } public static void SetWaitFormCaption(string text) { WaitFormService.Instance.SetFormCaption(text); } private static WaitFormService _instance; private static readonly Object syncLock = new Object(); public static WaitFormService Instance { get { if (WaitFormService._instance == null) { lock (syncLock) { if (WaitFormService._instance == null) { WaitFormService._instance = new WaitFormService(); } } } return WaitFormService._instance; } } private WaitFormService() { } private Thread waitThread; private WaitForm waitForm; public void CreateForm() { if (waitThread != null) { try { waitThread.Abort(); } catch (Exception) { } } waitThread = new Thread(new ThreadStart(delegate() { waitForm = new WaitForm(); Application.Run(waitForm); })); waitThread.Start(); } public void CloseForm() { if (waitThread != null) { try { waitThread.Abort(); } catch (Exception) { } } } public void SetFormCaption(string text) { if (waitForm != null) { try { waitForm.SetText(text); } catch (Exception) { } } } } }
1.3 使用WaitFormService提供的接口

try { WaitFormService.CreateWaitForm(); Assembly asmb = Assembly.GetExecutingAssembly(); Object obj = asmb.CreateInstance(className); Form frm = obj as Form; this.ShowMenu(frm); WaitFormService.CloseWaitForm(); } catch (Exception ex) { WaitFormService.CloseWaitForm(); }
參考文章
1. 飄落紙飛機,C# winform 多線程中創建等待窗體,2011。