学习之路五:再议自定义时钟类(跨线程间的访问操作) → 异步操作

   还记得两个月之前写了一篇通过线程来自定义时钟类,当时以为这是什么高深的技术呢,其实这其中的原理就是异步六种模式中一种!

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

  几天前偶然打开这篇文章看了看,有位兄弟说使用异步实现会比较好,于是就用了异步方式重构自己的时钟类 !

  在这期间遇到了一个问题:就是跨线程间的访问操作!  

  1.时钟代码如下:                          

  1   /*
2 知识点:
3 * 1.异步委托 → 相对于创建后台线程,异步委托优势比较明显
4 * 2.异步和事件的综合运用 → 按照规范来命名
5   */
6
7 public class MyTimerForAsync
8 {
9 //定义一些私有变量
10 private EventHandler<MyTimerEventArgs> _customerHandler; //定义委托变量,使用.NET Framework自己定义的委托类型
11 private int _distance; //间隔时间
12 private bool _flag = true; //启动时钟的标志
13
14      //定义事件
15 public event EventHandler<MyTimerEventArgs> Tick;
16
17 public MyTimerForAsync()
18 : this(1000)
19 { }
20
21 public MyTimerForAsync(int distanceTime)
22 {
23 this._distance = distanceTime;
24 ExecuteTimer();
25 }
26
27 //定义触发事件
28 public void OnTimer(object sender, MyTimerEventArgs timer)
29 {
30 try
31 {
32 while (_flag)
33 {
34 Thread.Sleep(this._distance);
35 EventHandler<MyTimerEventArgs> handler = Tick;
36 if (handler != null)
37 {
38 handler(this, timer);
39 }
40 }
41 if (this._flag == false)
42 {
43 this._customerHandler -= OnTimer; //撤销事件
44 }
45 }
46 catch (Exception ex)
47 {
48 throw ex;
49 }
50 }
51
52 //执行异步,执行函数
53 public void ExecuteTimer()
54 {
55 this._customerHandler = new EventHandler<MyTimerEventArgs>(OnTimer);
56 //开始异步调用,执行函数和回调函数
57 this._customerHandler.BeginInvoke(this, null, CallBackTimer, null);
58 }
59
60 //回调用函数作用:①获取返回值 ②结束异步操作
61 public void CallBackTimer(IAsyncResult ar)
62 {
63 if (_flag == false)
64 {
65 AsyncResult async = ar as AsyncResult;
66 EventHandler<MyTimerEventArgs> handler = async.AsyncDelegate as EventHandler<MyTimerEventArgs>;
67 handler.EndInvoke(ar);
68 }
69 }
70
71 #region 属性
72
73 //时钟的间隔时间
74 public int DistanceTime
75 {
76 get { return this._distance; }
77 set { this._distance = value; }
78 }
79
80 #endregion
81
82 #region 打开和停止异步操作
83
84 public void Start()
85 {
86 this._flag = true;
87 ExecuteTimer();
88 }
89
90 public void Stop()
91 {
92 this._flag = false;
93 }
94
95 #endregion
96 }
97
98 //创建实体类,还可以进异步完善,添加自己的信息
99 public class MyTimerEventArgs : EventArgs
100 {
101 public MyTimerEventArgs()
102 { }
103 }

    客户端调用:  

    

 1      private MyTimerForAsync _timer = new MyTimerForAsync(1000);  //实例化时钟类
 4         public FrmShowTimer()
5 {
6 //Control.CheckForIllegalCrossThreadCalls = false;
7 InitializeComponent();
8 this.txtDisplayTime.ReadOnly = true;
10 this._timer.Tick += new EventHandler<MyTimerEventArgs>(timer_Tick); //异步时钟,注册事件方法
17 }
34
35 //停止异步
36 void btnStopAsync_Click(object sender, EventArgs e)
37 {
38 _timer.Stop();
39 this.btnStopAsync.Enabled = false;
40 this.btnStartForAsync.Enabled = true;
41 }
42
43 //开始异步
44 void btnStartForAsync_Click(object sender, EventArgs e)
45 {
46 _timer.Start();
47 this.btnStopAsync.Enabled = true;
48 this.btnStartForAsync.Enabled = false;
49 }
68         //采用异步执行
69 void timer_Tick(object sender, MyTimerEventArgs e)  //注册的事件方法
70 {
71 //this.txtDisplayTime.Text = DateTime.Now.ToString();  //一开始是这样做的
72        //this.Invoke(new Action(() => this.txtDisplayTime.Text = DateTime.Now.ToString()));
73 this.txtDisplayTime.Invoke(new Action(() => this.txtDisplayTime.Text = DateTime.Now.ToString()));  //这是改进后的
         //如果采用的是控件的“Invoke”方法,匿名方法中必须要有对此控件进行操作!
         //不然就应该调用本窗体的“Invoke”方法 → this.Invoke
       }

 

  2.解决跨线程访问错误问题                        

    发生问题的原因:当你在一个窗体之外创建了一个新线程的时候,如果用这个线程去访问,或者控制窗体内部控件的时候,并且当你在DEBUG的时候才会出现“不允许跨线程访问操作”的问题!

    这种情况主要是发生在调试阶段,这是编译器为了线程安全而设置的一套规则,所以要尽量去避免她!

    ①第一种解决办法

      添加如下代码: Control.CheckForIllegalCrossThreadCalls = false; 

      这个代码意思是禁止编译器对跨线程访问做检查,这样就能忽视这种错误,但是不保险,可能今天对了明天就错了!    

    ②第二种解决办法

      ★小方法一:调用控件的“Invoke”或“BeginInvoke”方法,方法中的参数类型为Delegate,所以说里面可以传送任意的委托,不管参数多少,以及返回值!

      如:

 1      void timer_Tick(object sender, MyTimerEventArgs e)
2 {
3 //this.txtDisplayTime.Text = DateTime.Now.ToString();
4        //this.Invoke(new Action(() => this.txtDisplayTime.Text = DateTime.Now.ToString()));
5 this.txtDisplayTime.Invoke(new Action(() => this.txtDisplayTime.Text = DateTime.Now.ToString()));
6 this.txtDisplayTime.Invoke(new Action<string, string>(My)); //所以说可以送任何一个委托变量,只要最终继承于Delegate这个基类!
7 }
8
9 public void My(string a, string b)
10 {
11
12 }

       ★小方法二:使用整个窗体本身来调用 

        使用this.Invoke()或者“BegindInvoke()”方法来调用你要执行的方法!

        说实话使用BeginInvoke就是使用了异步操作,一般情况下会配合EndInvoke一起使用!  

    总结:总之,使用线程的方法有点缺陷,为了代码的健壮性,需要考虑周全,如果本人写的有问题,还希望大家多给点给点建议给我这个新手!

 

  参考文献:http://www.cnblogs.com/wangiqngpei557/archive/2011/08/24/2152096.html  //这篇也推荐

          http://blog.csdn.net/baple/article/details/4468891  

          http://www.cnblogs.com/fish-li/archive/2011/11/20/2256385.html  //这篇推荐  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时在底层功能的实现上。 平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时在底层功能的实现上。 平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时在底层功能的实现上。 平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值