實現 winform 異步跨線程訪問UI控件


        在開發winform時經常會用到多線程防止界面出現假死現象,比如當你單擊某個按鈕時,需要執行很多代碼,但是在執行過程中想實時的將當前執行的情況報告給用戶,類型進度條或文本什么的。

這個時候很顯然,如果你把要實現的內容放在按鈕方法里時,其實界面要等這個按鈕執行完后才能輸出來,這個時候就達不到我們的預期了;那么怎么才能解決問題呢。

我初略終結了一下有以下幾種方法:

    1.采用BackgroundWorker控件,這個控件將要實時輸出的內容寫在事件中;

 1 private void button1_Click(object sender, EventArgs e)
 2         {
 3             //異步執行邏輯
 4             backgroundWorker1.RunWorkerAsync();
 5         }
 6         private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
 7         {
 8             //實現業務邏輯
 9             int i = 5;
10             i = Math.Abs(i);
11             //報告當前處理進度
12             backgroundWorker1.ReportProgress(50);
13         }
14 
15         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
16         {
17             //當前進度
18             int cuur = e.ProgressPercentage;
19             //實現跨線程控件的輸出
20             this.label1.Text = cuur.ToString();
21         }
22 
23         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
24         {
25             //執行完畢可以報告信息
26             this.label1.Text = "ok";
27         }

   2.采用委托的方式實現靈活引用Invoke;

 1         private void button2_Click(object sender, EventArgs e)
 2         {
 3             //異步執行邏輯
 4             Thread thread = new Thread(ThreadFunc);
 5             thread.IsBackground = true;
 6             thread.Start();
 7         }
 8         private void ThreadFunc()
 9         {
10             //實現業務邏輯
11             int i = 5;
12             i = Math.Abs(i);
13             //報告當前處理進度
14             SetLabel(i.ToString());
15         }
16         //定義委托
17         delegate void SetLabelHandler(string text);
18         //實現方法
19         private void SetLabel(string text)
20         {
21             if (InvokeRequired)
22             {
23                 Invoke(new SetLabelHandler(SetLabel), text);
24             }
25             else
26             {
27                 this.label1.Text = text;
28             }
29         }

  3.采用Lamada表達式動態實現委托調用。

 1         private void button3_Click(object sender, EventArgs e)
 2         {
 3             //異步執行邏輯
 4             Thread thread = new Thread(Func);
 5             thread.IsBackground = true;
 6             thread.Start();
 7         }
 8         private void Func()
 9         {
10             //實現業務邏輯
11             int i = 5;
12             i = Math.Abs(i);
13             //報告當前處理進度
14             AsyncUI(() => { label1.Text = i.ToString(); });
15         }
16         public void AsyncUI(Action action)
17         {
18             if (InvokeRequired)
19             {
20                 Invoke(action);
21             }
22             else
23             {
24                 action();
25             }
26         }

 

以上是我總結的三種,至於有沒有其他方法,歡迎大家來拍磚,在這里我想推薦的是第三種方法,這個方法最靈活。

下面來談談我對這三種的看法:

對應第一種方法:使用簡單,拖控件就ok,但是對應需要顯示更負責的數據時比較麻煩;

對應第二種方法:可以不用拖控件來自由定制,但是同第一種方法一樣,如果需要顯示更多控件數據,也要定義很多方法和委托,太冗余累贅;

對於第三種方法:我個人非常喜歡,代碼在需要的時候動態使用,但是我也沒有仔細分析該方法的性能問題。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM