程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#後台線程工作時更新界面的處理方法

C#後台線程工作時更新界面的處理方法

編輯:C#入門知識

 

1.    需求:後台不間斷地進行某種工作,當獲得特定結果時彈出窗體進行提示,而工作繼續進行。那我的第一反應就是,該工作應放到後台線程中執行,條件滿足時創建/顯示提示窗體就行啦。代碼如下:

2.    ==========================Work.cs==============================

3.    using System;

4.    using System.Collections.Generic;

5.    using System.Linq;

6.    using System.Text;

7.    using System.Threading;

8.    using System.ComponentModel;

9.   

10.   namespace ThreadTest

11.   {

12.       public class Work

13.       {

14.           Thread thd;

15.           private static int count = 0;

16.  

17.           public Work()

18.           {

19.               thd = new Thread(new ThreadStart(thdDoWork));

20.               thd.Name = "NewThread";

21.           }

22.  

23.           WarningForm wf;//提示窗體

24.           private void thdDoWork()//後台工作

25.           {

26.               while (true)

27.               {

28.                   if ((count++ % 10) == 0)

29.                   {

30.                       wf = new WarningForm();//創建並顯示提示窗體

31.                       wf.Show();//將窗體顯示為非模式對話框

32.                   }

33.                   Thread.Sleep(600);

34.               }

35.           }

36.  

37.           public void ThdStart()

38.           {                        

39.               thd.Start();

40.           }

41.       }

42.   }

43.   ==========================Work.cs==============================

44.   同時呢,在WarningForm的構造函數中添加:

45.   Console.WriteLine("WarningForm Created in : " + Thread.CurrentThread.Name);

46.   這樣我們就能夠清楚的看到WarningForm是在哪一個線程中被創建顯示的。

47.   Debug,彈出提示窗口,而且後台工作沒有停止,但是提示窗口沒有響應,後台輸出“WarningForm Created in : NewThread”。我分析這是因為我們把提示窗體顯示為了非模式的,而後台線程顯示窗體後繼續執行,並沒有維護對提示窗體界面的響應,因此發生了以上現象。

48.  

49.   那我們把"wf.Show()"改為"wf.ShowDialog()"再試一下:

50.   Debug,彈出提示窗口,界面沒有死掉,後台輸出"WarningForm Created in : NewThread",但是後台的工作卻停止了。這是因為ShowDialog()將窗體顯示為模式的,也就是說該窗體的顯示阻塞掉了當前線程的運行。

51.  

52.   這樣看來,把提示窗體的顯示放到後台線程中是不行的,那麼,當後台線程需要顯示窗體時,如何在主線程中捕獲這種消息呢?

53.   哈,這位客官運氣真好,BackgroundWorker的ReportProgress(int percentProgress, object userState)方法最適合解決這個問題了。我們可以在主線程中注冊BackgroundWorker的ProgressChanged事件,當BackgroundWorker的對象調用ReportProgress()時,注冊到ProgressChanged事件的方法就會在主線程中執行,對後台線程的運行沒有任何影響,然後提示窗體是要顯示為模式的還是非模式的就看情況啦!

54.   我們修改Work.cs如下:

55.   ==========================Work.cs==============================

56.   using System;

57.   using System.Collections.Generic;

58.   using System.Linq;

59.   using System.Text;

60.   using System.Threading;

61.   using System.ComponentModel;

62.  

63.   namespace ThreadTest

64.   {

65.       public class Work

66.       {

67.           public BackgroundWorker bg;

68.           private static int count = 0;

69.  

70.           public Work()

71.           {

72.               bg = new BackgroundWorker();

73.           }

74.  

75.           private void bgDoWork(object sender, DoWorkEventArgs e)

76.           {

77.               Thread.CurrentThread.Name = "BgWorker";//修改後台線程的名字

78.               while (true)

79.               {

80.                   if ((count++ % 10) == 0)

81.                       bg.ReportProgress(count);//激活事件

82.                   Thread.Sleep(500);

83.               }

84.           }

85.  

86.           public void BgStart()

87.           {

88.               bg.WorkerReportsProgress = true;

89.               bg.DoWork += new DoWorkEventHandler(bgDoWork);

90.               bg.RunWorkerAsync();

91.           }

92.  

93.  

94.       }

95.   }

96.   ==========================Work.cs==============================

97.   同時在Form1.cs中如下編寫:

98.   ========================Form1.cs片段============================

99.           WarningForm wf;

100.        public Form1()

101.        {

102.            InitializeComponent();

103.            Thread.CurrentThread.Name = "MainThread";//修改主線程名字

104.        }

105.        private void button3_Click(object sender, EventArgs e)

106.        {

107.            //work為Work的對象

108.            work.bg.ProgressChanged += new ProgressChangedEventHandler(bg_ProgressChanged);//注冊這一事件

109.            work.BgStart();

110.        }

111.

112.        private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e)

113.        {

114.            //事件發生時顯示提示窗體

115.            wf = new WarningForm();

116.            wf.Show();

117.            //wf.ShowDialog();

118.        }

119.========================Form1.cs片段============================

120.Debug,輸出"WarningForm Created in : MainThread",可以看到窗體是在主線程中創建顯示的。而無論提示窗體是模式的還是非模式的,一切均能正常運行,到此,我們就實現了要求的功能哈哈!

121.

122.另外,請注意ReportProgress(int percentProgress, object userState),它第二個參數是object類型的,再加上如前所述的特性使得BackgroundWorker與界面進行通信的時非常的方便,我們在更新控件的時候可以用它。而如果使用Thread對象的話,則需要通過委托來調用控件的Invoke或者BeginInvoke方法,麻煩的多。但是我想後者肯定具有一些獨特的優點,目前我還不知道,求指點。。

 

本文出自 “小龐DE博客” 博客

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved