代码改变世界

多线程学习笔记一(转载)

2010-02-24 13:40  爱研究源码的javaer  阅读(220)  评论(0编辑  收藏  举报

本片(参考自codeproject)主要讲以下内容:
(一).Sleep和Join的用法
(二).Invoke和BeginInvoke的使用及区别
(三).Monitor类的使用
(四).AutoResetEvent使用

(一)1.Sleep()方法,调用后,线程会被阻止指定的时间,时间到了后,会继续执行。
线程需引用using System.Threading;命名空间。

Code

2.Join()方法,肯定有两个线程,Join才有用。
比如两个线程T1,T2
你在T2里写上T1.Join()的话,在执行的时候,T2会被Block,直到T1是的状态是stopped。

Code

(二).Invoke和BeginInvoke

Code

由于程序的并行执行,所以会交替输出。

Code

这个输出和上面输出差不多,也是交替输出的。

Code

BeginInvoke()的返回值是IAsyncResult类型的,表示dddddddddddddddd
EndInvoke()可以获得返回值。

Code

 

Winform中的多线程与UI

Code

大家看到上面这段代码没任何问题,就是往窗体上面添加个TextBox控件。

Code

大家再看这段代码,貌似也没有问题,但是运行的时候,就会抛出异常。
线程间操作无效: 从不是创建控件“Form2”的线程访问它。
出错的原因在于,主线程创建了form窗体,别的线程是不能操作它的。

 

Code

此处首先声明了委托MyDelegate。
 this.Invoke(delInstance); 中的this代表的是form对象,实际上还是主线程执行的AddControl
Invoke方法,会阻塞别的线程,直到自己的调用返回了,才继续往下执行,就是说Invoke()调用后会立即返回。
BeginInvoke就不会阻塞别的线程。这是二者的区别之一。

 

Code

上面的代码中,我们没必要用Invoke方法,因为我们是在主线程中,主线程中可以直接更新UI的。但是在一些情况下,我们不知道是否个别方法是在主线程里还是别的线程里执行的,并且,调用者不知道是否个别方法有更新UI的代码。所以,如果更新UI的话,应该切换到主线程里去执行。
其实没那么麻烦,InvokeRequired属性就是为了这个目的,如果当前线程不是主线程,InvokeRequired就返回true,是主线程就返回false。因此,任何更新UI的代码应该先判断InvokeRequired。

 

Code

 

(三).Monitor.Wait()方法,msdn解释:当前拥有指定对象上的锁的线程调用此方法以释放该对象,以便其他线程可以访问它。调用方在等待重新获取锁期间被阻止。当调用方需要等待另一个线程操作导致的状态更改时,将调用此方法。

当线程调用 Wait 时,它释放对象的锁并进入对象的等待队列。对象的就绪队列中的下一个线程(如果有)获取锁并拥有对对象的独占使用。所有调用 Wait 的线程都将留在等待队列中,直到它们接收到由锁的所有者发送的 Pulse 或 PulseAll 的信号为止。如果发送了 Pulse,则只影响位于等待队列最前面的线程。如果发送了 PulseAll,则将影响正等待该对象的所有线程。接收到信号后,一个或多个线程将离开等待队列而进入就绪队列。就绪队列中的线程被允许重新获取锁。

当调用线程重新获取对象上的锁后,此方法将返回。请注意,如果锁的持有者不调用 Pulse 或 PulseAll,则此方法将无限期地阻止。

调用方执行一次 Wait,与已为指定对象调用 Enter 的次数无关。概念上,Wait 方法存储调用方对对象调用 Enter 的次数,并按完全释放锁定对象所需要的次数调用 Exit。然后调用方在等待重新获取对象期间被阻止。当调用方重新获取锁时,系统按还原调用方的已保存 Enter 计数所需要的次数调用 Enter。调用 Wait 仅释放指定对象的锁;如果调用方是其他对象的锁的所有者,则不释放这些锁。

(四)

Code

 

Code
转自:http://www.cnblogs.com/lhking/archive/2009/07/26/1531513.html