.NET 线程学习笔记一
来源:互联网 发布:建php网站都要学什么 编辑:程序博客网 时间:2024/05/10 09:34
1.创建和启动线程要创建一个线程,需要创建一个Thread类型的对象。 static void Main(string[] args) { Thread thr = new Thread(Write); //创建一个线程 Write 为指定运行的方法 thr.Start(); //启动线程 Thread.Sleep(1000); //Sleep(int):静态方法,暂停当前线程指定的毫秒数; thr.Abort(); //终止线程 } public static void Write() { while (true) Console.WriteLine("."); }上面启动一个简单的线程示例。//Thread类有几个至关重要的方法,描述如下://Start():启动线程;//Sleep(int):静态方法,暂停当前线程指定的毫秒数;//Abort():通常使用该方法来终止一个线程;//Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;//Resume():恢复被Suspend()方法挂起的线程的执行;//IsAlive ; 如果调用它的线程还在运行,IsAlive返回true,否则,返回false;//Join 一直等待知道调用它的线程终止。其名称的含义为阻塞主调线程直到特定线程“连接”它//Thread类一个重要的属性IsBackground属性 如果为true为后台线程,如果为false为前台线程两者之间的唯一区别是,直到进程的所有前台线程都结束时后台线程才结束,而所有前台线程停止后,后台线程自动终止。//Thread.ThreadState 属性,这个属性代表了线程运行时状态,在不同的情况下有不同的值,我们有时候可以通过对该值的判断来设计程序流程。 //ThreadState 属性的取值如下: //Aborted:线程已停止; //AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止; //Background:线程在后台执行,与属性Thread.IsBackground有关; //Running:线程正在正常运行;//Stopped:线程已经被停止;//StopRequested:线程正在被要求停止;//Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);//SuspendRequested:线程正在要求被挂起,但是未来得及响应;//Unstarted:未调用Thread.Start()开始线程的运行;//WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;调用传参的线程。。 public class MyThread { public void Run() { Thread thr = new Thread(this.Write); thr.Start(5); Thread.Sleep(1000); thr.Abort(); } public void Write(object num) { int count = (int)num; while (count > 0) { Console.WriteLine("."); count--; } } } 多线程同步。使用锁(lock)实现线程同步,lock所用于控制对对象中代码块的访问。当一个线程锁定一个对象时,其他线程就不能访问已锁定的代码块。只有当线程释放该锁时,其他线程才能使用该对象。 class Example { static void Main(string[] args) { new MyThread().Run(); } } public class MyThread { public void Run() { int[] arr1 = new int[] { 1, 2, 3, 4, 5, 6 }; //21 int[] arr2 = new int[] { 6, 7, 8, 9, 10, 11 }; //51 Thread thr1 = new Thread(this.Write); Thread thr2 = new Thread(this.Write); thr1.Start(arr1); thr2.Start(arr2); Console.Read(); } int sum; Object obj = new Object(); public void Write(object num) { lock (obj) { int[] count = (int[])num; sum = 0; foreach (int i in count) { sum += i; Console.WriteLine("当前进行累加数值为:" + sum); Thread.Sleep(500); } Console.WriteLine("方法完成:" + sum); } } }同步2. 使用Monitor类和锁(lock) 实现同步 Monitor定义了许多控制或管理同步机制的方法。例如要锁定一个对象,可调用Enter().要释放对象则调用Exit()。这两种方法的定义格式如下:public static void Enter(object syncOb) public static void Exit(object syncOb) 其中,syncOb是同步时使用的对象。如果调用Enter()是对象不可用,那么主线程将等待,直到它可用为止。由于lock的作用等同于Enter()和Exit(),因此一般不需要调用后两种方法。出于这个原因,lock是进行C#变成时获得对象锁的首选方法。TryEnter()是Moniter()中的一种有用的方法,下面给出它的一种形式:public static bool TryEnter(object syncOb) 如果主线程获得syncOb上的一个锁,那么上面的方法返回true,否则返回false.在任何情况下,主调线程都不会进入等待状态。当对象为不可用时,可以使用该对象来实现替换。 Wait(),Pulse()和PulseAll()方法由Monitor类定义,只能从锁定的代码块内调用这些方法。线程在被暂时中断运行时调用Wait()方法,这使得此线程暂时进入休眠状态并释放对象的锁以允许其他线程使用此对象。然后,当其他线程使用完锁对象并调用Pulse()或PulseAll()时,唤醒休眠的线程。Pulse()被调用时将恢复等待锁的线程队列中的第一个线程。而调用PulseAll()表示将锁释放给所有正在等待的线程。下面给出Wait()的两种常用形式: #region 闹钟类 public class TickTock { object lockOn = new object(); public void Tick(bool running) { lock (lockOn) { if (!running) { Monitor.Pulse(lockOn); return; } Console.WriteLine("Tick"); Monitor.Pulse(lockOn); Monitor.Wait(lockOn); } } public void Tock(bool running) { lock (lockOn) { if (!running) { Monitor.Pulse(lockOn); return; } Console.WriteLine("Tock"); Monitor.Pulse(lockOn); Monitor.Wait(lockOn); } } } #endregion #region 线程封装类 public class MyThread1 { public Thread Thrd; TickTock ttOb; public MyThread1(string name, TickTock tt) { Thrd = new Thread(this.run); ttOb = tt; Thrd.Name = name; Thrd.Start(); } public void run() { if (Thrd.Name == "Tick") { for (int i = 0; i < 5; i++) ttOb.Tick(true); ttOb.Tick(false); } if (Thrd.Name == "Tock") { for (int i = 0; i < 5; i++) ttOb.Tock(true); ttOb.Tock(false); } } } #endregion #region 调用 class ThreadFour { static void Main(string[] args) { TickTock tt = new TickTock(); MyThread1 mt1 = new MyThread1("Tick", tt); MyThread1 mt2 = new MyThread1("Tock", tt); mt1.Thrd.Join(); mt2.Thrd.Join(); Console.WriteLine("Clock Stopped"); Console.Read(); } } #endregion