关于C#中的多线程的问题我在以前的-多线程应用实例(多点通讯)中已经提到过了,但是关于多线程的应用还有很多方面没有涉及到。下边我将通过几个小例子来具体的说明一下在C#中如何来使用多线程。(特别是Lock的使用)
参考网址http://www.csyouth.com.cn/detail.asp?unid=3192
http://www.chinacs.net/archives/5/2001/08/25/416.html
http://community.rising.com.cn/Forum/msg_read.asp?FmID=55&SubjectID=5184739&page=1
在多线程的程序中经常会遇到,多个线程要对一个对象进行操作的情况这样的话如果没有一个线程的控制的话一定会造成数据的损坏。比如两个现成要对同一个数组进行操作一个需要对数组进行加操作而另一个则要进行减操作。在这种情况下如果没有lock那就会很容易的出现超出数组界限的事情。
下边我就介绍一下在C#中Lock的用法
启动线程很容易,但是让他们协调工作却很难,设计一个多线程的程序时最难的就是计算出并发的线程会在哪里冲突并用同步逻辑来阻止冲突的发生。
.NET框架提供了下面的几个线程同步类:
AutoResetEvent:阻塞线程直到另一个线程设置事件u
Interlocked:以线程安全的方式进行简单操作、如递增或递减整数u
ManualResetEvent:阻塞一个或多个线程直到另一个线程设置事件u
Monitor:防止一个以上的线程同时访问一个资源u
Mutex:防止一个或多个以上的线程同时访问一个资源,并能跨越应用程序或进程的边界u
ReaderWriterLock:使多个线程可以同时读取一个资源,但不允许重叠的读写或写操作u
在以上几个类里面我们用得最多是Monitor,下面将重点对Monitor类进行讲解:
Monitor的几个重要的方法:
Enter:在访问资源前调用并在该资源上声明一个锁以判断是否该资源被其他资源所占用,如果是则该线程被阻塞直到可以获得该资源为止。
Exit:在访问完该资源后调用以释放对资源的锁便于其他线程访问。u
Wait:暂时放弃调用线程对该资源的锁。u
Pluse:通知在Wait中阻塞的线程,使得下一个等待线程在当前线程释放锁后可以运行。
在C#里有lock关键字以取代Monitor的Enter和Exit,在功能上
lock ( SomeResource )
{
//您的处理代码
}
等价于:
Monitor.Enter( SomeResource );
try
{
//您的处理代码
}
finally
{
Monitor.Exit( );
}
下面是我自己写的一段代码主要是利用了lock和Monitor。Wait Monitor.pluse
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;
namespace yangpr
{
class Program
{
static void
{
Glass glass = new Glass();
Thread zhang = new Thread(glass.Add);
Thread li = new Thread(glass.reduce);
zhang.Start();
li.Start();
zhang.Join();//对线程调用Join()方法会令调用线程暂停执行直到被调用线程结束。
li.Join();
zhang.Abort();
li.Abort();
}
}
class Glass
{
public static ArrayList PeopleCollect = new ArrayList();
public void Add()
{
lock (PeopleCollect)
{
Monitor.Wait(PeopleCollect);//把自己暂时的堵塞起来让别的线程先执行
PeopleCollect.Add(new People());
Console.WriteLine("这个班级里现在有同学{0} 名", PeopleCollect.Count);
Monitor.Pulse(PeopleCollect);
Monitor.Wait(PeopleCollect);
}
}
public void reduce()
{
lock (PeopleCollect)
{
if (PeopleCollect.Count > 0)
{
PeopleCollect.RemoveAt(0);
}
else
{
Monitor.Pulse(PeopleCollect);//通知被堵塞的线程准备一旦PeopleCollect对象被线程释放就马上执行
Console.WriteLine("班里边一个同学都没有怎么减呀");
Monitor.Wait(PeopleCollect);
if (PeopleCollect.Count > 0)
{
PeopleCollect.RemoveAt(0);
}
//return;
}
Console.WriteLine("这个班级里现在有同学{0} 名", PeopleCollect.Count);
}
}
}
class People
{
public People()
{
}
}
}
线程的应用还有一些方面在上边的是示例中没有被提及到下边我就简单的介绍一下。例如线程的挂起,和解除挂起。设置线程的优先级。停止一个线程。
杀死一个线程
参考网址:
http://www.cnblogs.com/Sandheart/archive/2005/05/08/150836.aspx线程类的 Abort()方法可以永久的杀死一个线程。在杀死一个线程起前应该判断线程是否在生存期间。
if ( thread.IsAlive )
{
thread.Abort();
}
停止一个线程
Thread.Sleep 方法能够在一个固定周期类停止一个线程
thread.Sleep();
设定线程优先级
线程类中的ThreadPriority 属性是用来设定一个ThreadPriority的优先级别。线程优先级别包括Normal, AboveNormal, BelowNormal, Highest, and Lowest几种。
thread.Priority = ThreadPriority.Highest;
挂起一个线程
调用线程类的Suspend()方法将挂起一个线程直到使用Resume()方法唤起她。在挂起一个线程起前应该判断线程是否在活动期间。
if (thread.ThreadState = ThreadState.Running )
{
thread.Suspend();
}
唤起一个线程
通过使用Resume()方法可以唤起一个被挂起线程。在挂起一个线程起前应该判断线程是否在挂起期间,如果
线程未被挂起则方法不起作用。
if (thread.ThreadState = ThreadState.Suspended )
{
thread.Resume();
}
浙公网安备 33010602011771号