免费邮箱 |加入收藏 | 会员中心 | 我要投稿 | RSS
您当前的位置:首页 > .NET专区 > ASP.NET技巧

初识C#线程

时间:2011-05-16 20:07:05  来源:站内  作者:潘春会


程序清单B
using System;
using System.Threading;
namespace TaskDemo {
   public class MyTask {
      public Thread m_thread;
      string m_name;
      public MyTask(string name) {
      m_name = name;
      m_thread = new Thread(new ThreadStart(Worker));
     }
      private void Worker() {
        Console.WriteLine("Hello, ");
         Thread.Sleep(1500);
        Console.WriteLine(m_name);
      }
   }       
class TaskDemo1 {
         static void Main(string [] args)  {               
         MyTask task1 = new MyTask("Bill");
         MyTask task2 = new MyTask("Steve");
         task1.m_thread.Start();
         task2.m_thread.Start();
         }
}
}




你甚至可以通过在保存线程的任务中定义字段的方法提供Task对象的某种返回值,在线程完成前设置这一返回值,最后在这项任务完成以后从启动这项任务的线程读取它。

你可以暂停一个线程、等待其他线程完成其任务。你可以在打算采集返回结果的时候执行两种操作,在三个分隔的线程之间执行数据库更新但直到所有线程都结束时才想进行数据处理也可以采用以上两种操作。该技术如程序清单C所示。

程序清单C:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=3


这里,我们采用了程序清单A的代码创建程序。这次我们运行两个线程,每一个线程完成同以前一样的任务。调用两个线程的Start () 方法之后调用它们的Join()方法。对线程调用Join()方法会令调用线程暂停执行直到被调用线程结束。因此thread1.Start ()方法会令主线程暂停直到thread1完成。然后我们对thread2执行同样的操作。结果,主线程直到thread1和 thread2都完成了才最后完成。

这个例子的思想分为两部分。首先,某一个线程不能调用另一线程上的Join方法除非后者已经启动。第二,有多于两种形式的Join可以设定调用线程继续运行的超时时间哪怕被调用线程仍在运行。

计算机科学中经常会提到看门狗概念,所谓看门狗(watchdog)其实就是负责保证功能正确性或者处理不正确功能的实体。另一种实体,也就是常用的看门狗计时器(watchdog timer)则通常负责保证另一任务在合理的时间内按时完成。程序清单D所示就是实现看门狗计时器的简单实现机制。

程序清单D:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=4

thread1启动之后我们就加入该线程但提供了10秒钟的超时时间。因为thread1内置15秒暂停设置,所以在加入超期之后还会继续存活。主线程则测试thread1.IsAlive,如果它还活动则终止线程。

同步和监视器
同步指的是保证一次一节代码中只有一个线程在执行的措施。讨论同步技术已经超出了本文所涉及的主题范围,但单个线程模块之内为可靠起见实际上会产生为数不少的构造。然而,它们中的大多数在这些代码块的外部,在大多数时间内都工作很正常,这样,我们一直所熟知的“如果编译通过并且得到我期望的答案那么它就是正确的”这种说法在这里就不一定成立了。这就是多线程为什么如此危险的部分原因。

监视器是最基础的同步构造。任何对象都有自己关联的监视器,一个监视器只能分配给一个对象。监视器上有一个“锁(lock)”,这个锁可以在某一时刻被唯一线程获得。在另一线程可以获得这把锁之前必须先释放它。你可以声明某个对象对所有线程可见来保护某一段代码,比如类字段等。你还可以在实施某种操作之前让某段代码从监视器那里获得对象锁,然后在操作完成之后释放这把锁。该构造的示范如程序清单E所示。

程序清单E:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=5

这里我们声明了一个对象myLockObject,该对象的唯一目的就是提供同步监视器。在 SayHello方法中,无论何时只要需要我们就允许两个线程打印出“Hello”的字样。然而,现在我们就通过myMonitorObject所关联的监视器控制了“Wonderful”和“World”的打印,这样,一个线程在被允许开始打印之前另一线程必须完成两次打印。

实现以上机制还可以采用另两种技术——lock()关键词何MethodImplAttribute属性。示例请参看程序清单F。

程序清单F:
http://builder.com.com/utils/sidebar.jhtml?id=u00220020531pcb01.htm&index=6

我们用lock(…){ … }代替Monitor.Enter(…) and Monitor.Exit(…)构造。这些构造在效果上是相同的,只不过后者相比前者更为便捷些。我们还增加了一个方法SayHello2 (),它具有属性MethodImpl。这一属性指定了将被同步的全部方法。实质等价于在包含这些同步方法的类型对象被允许调用方法之前强迫调用代码获取类型对象关联的监视器上的锁。这比在lock(){…}语句中封装方法代码可清楚多了。注意,文档中定义该属性为MethodImplAttribute,但它的实现却叫做MethodImpl。根据声明属性的陈述习惯,也许微软的某个开发人员自己可能没注意到这一疏忽。
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
如何找出DHCP地址池里未使用的IP地址
如何找出DHCP地址池里
国内常用的DNS列表
国内常用的DNS列表
Linux邮件服务器软件比较
Linux邮件服务器软件比
学用纯CSS打造可折叠树状菜单
学用纯CSS打造可折叠树
相关文章
栏目更新
栏目热门