学习之路三:关于运用单线程和委托以及事件自定义Timer类

时间:2022-05-14 14:34:43

  经过一个星期的线程学习,感觉上对线程的认识还是一头雾水,不过在这中间却对委托和事件有了一定的认识和感悟!

  在此记录我的学习感受,附带几个大牛的博客文章,可以去看看!

  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)

    ④最后调用这个线程,就会实现即时刷新

    图示:    

    学习之路三:关于运用单线程和委托以及事件自定义Timer类

 

  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程序):    

    学习之路三:关于运用单线程和委托以及事件自定义Timer类    

 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) 中两个参数的理解有了更加清除的认识了!    

    学习之路三:关于运用单线程和委托以及事件自定义Timer类

    对两个参数的理解:

    ①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菜单 → 

    学习之路三:关于运用单线程和委托以及事件自定义Timer类

    这样就搞定了,但是我查了一些资料,说是因为我没有释放资源,我知道可能是我的线程资源没有释放,但是我思考了还几个晚上都没有想出什么方案来解决,其实做这个东西说白了只是能促进我对委托,线程,事件的理解,其它也就没什么了!

    如果大家知道是什么情况,请留言给我!Thanks!

  感谢一位网上的兄弟对我的指导!

  在学习中深入,在实践中提高,在这边祝大家元旦快乐,前几天因为在网上团购了一张电影票,所以准备元旦去看场电影,潇洒下,o(∩_∩)o .....