學習之路三:關於運用單線程和委托以及事件自定義Timer類


  經過一個星期的線程學習,感覺上對線程的認識還是一頭霧水,不過在這中間卻對委托和事件有了一定的認識和感悟!

  在此記錄我的學習感受,附帶幾個大牛的博客文章,可以去看看!

  http://www.cnblogs.com/kevin-moon/archive/2009/04/24/1442469.html

  http://www.cnblogs.com/rentiansheng/archive/2011/02.html ,講的線程知識還是很深入的!

  好了,言歸正傳,Let‘s Go...

  1.前言                          

    大家都知道當你想每間隔一段時間就動態的刷新數據或制作一個動態的時鍾時(類似於這樣的需求),大家都會想到使用.NET Framework中的Timer類,而在.NET Framework它又分為三種類型 

· System.Windows.Forms.Timer     

· System.Threading.Timer

· System.Timers.Timer

    對於以上三種類的使用大家應該多少有點接觸,注冊事件,綁定要執行的方法,然后設置一下時鍾的間隔時間,當程序運行時就會自動的觸發了!

 

  2.思考                          

    如果大家不使用上面三種類,會不會有其它的辦法來實現間隔幾秒刷新數據或制作一個動態時鍾(這種實現都基於Winform程序)呢?

    答案是肯定的!

  

  3.思路                           

    運用的知識:

    ①委托

    ②事件

    ③線程

    實現思路:

    ①在客戶端通過注冊事件來綁定要執行的方法

    ②在服務端讓執行事件的方法置於一個無限循環的環境中

    ③創建一個線程,把執行事件的方法交給線程,並設置線程為后台運行和線程的間隔時間(Thread.Sleep)

    ④最后調用這個線程,就會實現即時刷新

    圖示:    

    

 

  4.代碼實現                          

 1      /*
2 自定義時鍾類,線程和委托,事件的綜合運用
3 * 按照規范來命名
4 */

5 public delegate void CustomHander(object sender, CustomEventArgs e); //命名規范 → 委托名 + Handler,參數必須一致
6 public class CustomTimer : IDisposable

7 {
8 private CustomHander _customHandler; //定義一個委托變量
9 private int _distance; //間隔的時間
10 private int _start; //啟動時間
11 private bool _flag = true; //用來做時鍾啟動和停止的標志,默認值為True
12 private Thread _thread; //定義一個線程
13 private CustomEventArgs _customEventArgs = new CustomEventArgs("Yang Cao Gui"); //定義一個實體信息類
14

15 public event CustomHander CustomTick;
16
17 public CustomTimer() // 構造函數的重載,減少代碼量
18 : this(null, 1000, 0)

19 { }
20 public CustomTimer(int distance)
21 : this(null, distance, 0)
22 { }
23 public CustomTimer(int distance, int start)
24 : this(null, distance, start)
25 { }
26 public CustomTimer(CustomHander handler, int distance, int start)
27 {
28 this._customHandler = handler;
29 this._distance = distance;
30 this._start = start;
31 Connect(); //調用線程
33 }

34
35 private void OnCustomTick() //執行事件的方法一般為 On + 事件名 ,這個就是我所謂的執行事件的方法,.NET Framework中都是這樣命名的
36 {

37 try
38 {
39 while (true) //寫一個無限循環
40 {

41 if (this._flag == false) //判斷是否為啟動還是停止
42 {

43 return;
44 }
45 Thread.Sleep(this.DistanceTime);
46 if (this._customHandler == null)
47 {
48 this._customHandler = CustomTick; //這樣寫那么定義的委托就會生成一個委托鏈
49 }

50 if (this._customHandler != null)
51 {
52 this._customHandler(this, _customEventArgs);
53 }
55 }
56 }
57 catch (Exception ex)
58 {
59 throw ex;
60 }
61 }
62
63 private void Connect() //這個方法是把客戶端和Timer連接起來,用來創建線程!
64 {

65 if (this.StartTime > 0)
66 {
67 Thread.Sleep(this.StartTime);
68 }
69 if (this._thread == null) //這邊判斷很重要
70 {

71 this._thread = new Thread(new ThreadStart(OnCustomTick)); //把執行事件的方法綁定到一個單線程中去
72 this._thread.IsBackground = true; //指定為后台運行
73 this._thread.Start();

74 }
75 }
76
77 public void Start() //開始時鍾
78 {

79 this._flag = true;
80 //因為這邊會出現先停止在開始的邏輯,所以必須要在調用一下連接方法
81 this.Connect();

82 }
83
84 public void Stop() //停止時鍾
85 {

86 this._flag = false;
87 }
 94         public void Dispose()       //釋放資源
95 {

96 //this._thread.IsBackground = false;
97 this._thread.Abort();

98 this.Dispose();
99 GC.Collect();
111 }
112
113 public int DistanceTime //獲取和設置間隔時間
114 {

115 get { return this._distance; }
116 set { this._distance = value; }
117 }
118
119 public int StartTime //設置和獲取啟動時間
120 {

121 get { return this._start; }
122 set { this._start = value; }
123 }
124 }
125
126 public class CustomEventArgs : EventArgs //自定義自己的實體信息類,並且繼承與EventArgs,因為這是規范
127 {
128 public CustomEventArgs(string message)
129 {
130 this.Message = message;
131 }
132
133 public string Message
134 { get; set; }
135 }

     客戶端調用(Winform程序):    

        

 1     public partial class Form1 : Form
2 {
3 MyCustom.CustomTimer customTimer;    //定義一個全局變量
4
5 public Form1()
6 {
7 InitializeComponent();
8 }
9
10 private void Form1_Load(object sender, EventArgs e)
11 {
12 this.textBox1.Text = DateTime.Now.ToString();
13 customTimer = new MyCustom.CustomTimer(1000, 0);  //構造函數重載,初始化一些變量
14 customTimer.CustomTick += new MyCustom.CustomHander(customTimer_CustomTick); //注冊事件
15 this.button1.Click += new EventHandler(button1_Click);
16 this.button2.Click += new EventHandler(button2_Click);
17 //customTimer.Close();
18 }

19
20 void customTimer_CustomTick(object sender, MyCustom.CustomEventArgs e)
21 {
22 this.textBox1.Text = String.Empty;
23 this.textBox1.Text = DateTime.Now.ToString();
25 }

27
28 void button2_Click(object sender, EventArgs e)    //時鍾停止
29 {
30 customTimer.Stop();
32 }
33
34 void button1_Click(object sender, EventArgs e)    //時鍾開始
35 {
36 customTimer.Start();
37 }
38 } 

     

  5.總結                              

    通過這個小實驗,我也對.NET Framework中的委托和事件機制有了一定的基礎了解,尤其是對 → void button2_Click(object sender, EventArgs e) 中兩個參數的理解有了更加清除的認識了!    

    

    對兩個參數的理解:

    ①object sender :在執行事件的時候,此參數的值為“this”,也就是說這個參數是包含這個事件的對象,如果要使用它可以進行強制轉化,因為它是object類型,如:      

Button btn = (Button)sender as Button; 
MessageBox.Show(btn.Text); 

       這是一個Button按鈕的轉換,其它控件也是這樣做的,尤其是大家在使用GridView的時候,特別需要這樣的轉化!

     ②EventArgs e :這個其實是很好理解,因為大部分控件都有自己的實體信息類,也就說這個對象想通過事件傳遞一些信息,那么就只有通過這個信息類來傳遞了,而且所有的信息類都必須繼承與EventArgs這個基類!如:

void button2_Click(object sender, EventArgs e)
{
  customTimer.Stop();
  Button btn = (Button)sender as Button;
  MessageBox.Show(btn.Text);  //因為按鈕沒有自己的信息類,所以它就直接傳的是EventArgs這個基類,所以就沒有任何關於它的信息!
}

如果有興趣的話可以使用Reflector來查看其它控件的信息類!

 

  6.疑問                              

    一開始我在做測試的時候,當程序運行幾次后就會出現 → “TestCustomTimer.vshost.exe” 這個文件正在被其它進程使用,然后使用任務管理器強制關閉,但是關了又會繼續出現!

    最后通過右擊項目屬性 → 找到Debug菜單 → 

    

    這樣就搞定了,但是我查了一些資料,說是因為我沒有釋放資源,我知道可能是我的線程資源沒有釋放,但是我思考了還幾個晚上都沒有想出什么方案來解決,其實做這個東西說白了只是能促進我對委托,線程,事件的理解,其它也就沒什么了!

    如果大家知道是什么情況,請留言給我!Thanks!

  感謝一位網上的兄弟對我的指導!

  在學習中深入,在實踐中提高,在這邊祝大家元旦快樂,前幾天因為在網上團購了一張電影票,所以准備元旦去看場電影,瀟灑下,o(∩_∩)o .....

 


免責聲明!

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



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