开始学习线程了,做个记录:)
1、在这个小例子里,将创建一个新线程,我们将用两个线程演示多线程的工作方式。
程序的运行结果如下:
MainThread: 0
NewThread: 0
MainThread: 1
NewThread: 1
MainThread: 2
NewThread: 2
MainThread: 3
NewThread: 3
MainThread: 4
NewThread: 4
在上面的例子中,Thread.Sleep(n)方法把当前线程置于n毫秒的休眠状态。在主函数中定义了一个新的线程,其中它的起点是函数ThreadStartMethod(),然后包含了Start()方法开始执行。运行例子,就会了解线程间的切换(让CPU从运行一个线程转到另一个线程),也就是让线程几乎同时运行,为了能看哪个线程运行更快我把主线程设置比新线程少100毫秒。
2、再看下面这个示例。
怎么让主线程等待呢。可以通过ManualResetEvent 或 AutoResetEvent的WaitOne()方法。
3、假如我们不想在开始一个新线程后就让它马上运行结束,也就是说,开启了一个新线程后让它运行,然后在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
这时就可以这样定义:
public static ManualResetEvent manualEvent = new ManualResetEvent(false);
ManualResetEvent允许线程通过发信号互相通信,构造函数的布尔值可以设置ManualResetEvent 的初始状态,false表示初始状态为非终止状态。
像本例中初始化时直接把false作为start的初始状态,也就是通知另一个线程,让它等待一个或多个线程。
等待线程就要调用:
manualEvent.WaitOne();
所以等待线程就要无限期的阻塞并等待类来通知。
发信号的线程调用Set()方法发送信号。
manualEvent.Set();
这样等待线程就会被通知,值变为true,同时停止等待。
运行的结果如下:
Thread: Waiting for a Signal.
MainThread: 0
MainThread: 1
MainThread: 2
Thread: Get a Signal.
MainThread: 3
NewThread:0
MainThread: 4
NewThread:1
Main: Waiting for thread to stop.
NewThread:2
Main: Waiting for thread to stop.
NewThread:3
Main: Waiting for thread to stop.
NewThread:4
Main: Waiting for thread to stop.
4、在下面的例子中,学习一下AutoResetEvent的用法。
在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似。从字面意思看,它们都表示是一个事件(Event)。这两个类都有WaitOne方法,这个方法被调用后,当前的线程(即是调用这个方法的线程)暂停运行(可以看做等待事件触发),直到事件被触发(即另外的线程调用了它的Set方法)
ManualResetEvent说明这个事件被触发后(Set方法被调用),是要手工进行重置的(即调用Reset方法),否则再次调用它的WaitOne方法是没有用的(也就是调用WaitOne的线程不会停下等待事件触发,而是继续执行)。 它提供手工重置的方法是调用Reset方法。
AutoResetEvent则是Set被调用后,如果WaitOne再次被调用,当前的线程还是会被暂停的,也就是不用手工调用它的Reset方法,就能使WaitOne再次生效。
看下面两个示例:
示例1:
运行结果如下:
ThreadMethod.
ThreadMethod.
示例2:这个示例演示了ManualResetEvent调用过Set方法后,再次调用WaitOne是无效的,必须先调用Reset方法
运行结果如下:
ThreadMethod.
另外这两个类的区别还有一点,就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。
5、上面叙述了AutoResetEvent和ManualResetEvent的主要区别,对于这个区别希望大家不要视而不见。也就是AutoResetEvent一次只唤醒一个线程,而ManualResetEvent则可以唤醒多个线程。再举个小例子详细说明一下。
比如你想送花给一个MM,托了一个送花的小伙子送了过去,而你希望当MM收到花之后就立即打个电话过去告诉她。
但问题是你不知道花什么时候才送到MM的手里,打早了打迟了都不好,这时你可以使用ManualResetEvent对象帮忙。当委托小伙子送花过去的时候,使用ManualResetEvent的WaitOne方法进行等待。当小伙子把花送到MM的手中时,再调用一下ManualResetEvent的Set方法,你就可以准时地打电话过去了。另外ManualResetEvent还有一个Reset方法,用来重新阻断调用者执行的,情况就好比你委托了这个小伙子送花给N个MM,而又想准时地给这N个MM打电话的情况一样。