Threads concepts
(一)线程--简述线程概述及原理
线程是程序执行的基本原子单位. 一个进程可以由多个线程组成.
在分布式编程中,正确使用线程能够很好的提高应用程序的性能及运行效率.
实现原理是将一个进程分成多个线程,然后让它们并发异步执行,来提高运行效率.
并发执行并不是同时执行(占有CPU),任意时刻还是只能有一个线程占用CPU,
只不过是它们争夺CPU频繁一些,感觉到他们似乎都在运行.
下面通过一个简单的例子来说明一下它的工作原理
设一个进程要完成两个任务:任务1和任务2
并且任务1要经历: A1->B1->C1三个步骤才能完成
任务2要经历: A2->B2->C2三个步骤才能完成
I.如果两个任务同步执行的话完成两个任务是这样执行的:
花费时间段: 1 2 3 4 5 6
A1->B1->C1->A2->B2-C2
这样从A1一直到c2只能一个一个地执行. 当A1占用CPU执行时,从B1到C2线程只能在等待.
甚至它们不相互竞争同一个资源时,也要等待前面的执行完成,自己才能执行
II.如果两个任务异步执行的话完成两个任务是这样执行的:
花费时间段: 1 2 3 4 5 6
A1->B1->C1
A2->B2->C2
这样,任务1和任务2就分成两个独立的执行对象. 也就是说:
A1->B1->C1 和 A2->B2->C2 是并发执行的. 当A1在执行某个运算时,A2线程可以去做其它
的一些事情,比如访问磁盘等外部设备等
对比一下I和II两种执行方式,完成所有任务I需要6个时间段,
而II只需要3个时间段就完成了(事实上会多一点,因为方式II中的线程轮询CPU比较频繁,在轮询CPU时会花费一些时间);方式II所需时间是I的一半. 所以II完成整个任务要快.
另一方面,II执行方式,完成每个任务所需的时间可能会花费时间长些,因为I方式是各个线程依次占用CPU执行,当A1占用CPU时,CPU就只为A1服务,当A1执行完后,才让出CPU。II情况就不一样了,它们是异步执行的,轮流使用CPU频繁,经常让出或占有CPU,执行每个线程完成的时间也就会相对长些.
一般情况下,如果多个线程在执行时都要抢占某一个资源或某几个资源,则最好不用异步线程执行.因为它们是并发执行,很可能同时争夺某个资源有CPU,这时要么执行资源分配算法(比如要判断哪个线程优先级高,这要花费时间),或者是按时间片算法(这样要付出 轮询CUP/交接/让出CPU 所需的时间). 如果多个线程所需要的系统资源是比较均匀的,这时完全可以让它们异步并发执行,比如: 当一个线程在给客户端
发出消息后,并不是一直在等待此客户端回应,它可以继续处理下一个客户端请求.
(二)线程--通过委托异步调用方法
(一).描述
先运行个简单的线程示例,认识一下线程
通过委托调用方法,以及使用AsyncResult判断线程的状态
(二).代码
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace 通过委托异步调用方法
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//要调用的动态方法
public string MyMethod1()
{
return "Hello Word1";
}
//要调用的静态方法
public static string MyMethod2()
{
return "Hello Word2";
}
}
class Class1
{
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main(string[] args)
{
MyClass myClass = new MyClass();
//方式1: 声明委托,调用MyMethod1
MyMethodDelegate d = new MyMethodDelegate(myClass.MyMethod1);
string strEnd = d();
Console.WriteLine(strEnd);
//方式2: 声明委托,调用MyMethod2 (使用AsyncResult对象调用)
d = new MyMethodDelegate(MyClass.MyMethod2); //定义一个委托可以供多个方法使用
AsyncResult myResult; //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
myResult = (AsyncResult)d.BeginInvoke(null,null); //开始调用
while(!myResult.IsCompleted) //判断线程是否执行完成
{
Console.WriteLine("正在异步执行MyMethod2 ..");
}
Console.WriteLine("方法MyMethod2执行完成!");
strEnd = d.EndInvoke(myResult); //等待委托调用的方法完成,并返回结果
Console.WriteLine(strEnd);
Console.Read();
}
}
}
(三)线程--等待句柄
(一).描述
本示例代码实现线程等待等待执行,比如一个线程在执行之前要等待所有其它线程或某个线程
先执行完成,或者等待其它线程至少一个执行完成.
(二).代码
using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace 等待句柄
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//要调用方法1
public string Write1()
{
for(double i = 0; i < 100000000000;i++) //此数值大小可以根据自己的环境修改,
//目的是让此方法延长时间而已
{
//延长时间(模拟实际任务)
}
Console.WriteLine("执行方法1");
return "";
}
//要调用方法2
public string Write2()
{
Console.WriteLine("执行方法2");
return "22222222222222";
}
//要调用方法3
public string Write3()
{
Console.WriteLine("执行方法3");
return "33333333333333";
}
[STAThread]
static void Main(string[] args)
{
MyClass myClass = new MyClass();
MyMethodDelegate d1 = new MyMethodDelegate(myClass.Write1);
MyMethodDelegate d2 = new MyMethodDelegate(myClass.Write2);
MyMethodDelegate d3 = new MyMethodDelegate(myClass.Write3);
AsyncResult myResult1,myResult2,myResult3; //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
myResult1 = (AsyncResult)d1.BeginInvoke(null,null); //调用
myResult2 = (AsyncResult)d2.BeginInvoke(null,null);
myResult3 = (AsyncResult)d3.BeginInvoke(null,null);
//建立WaitHandle数组对象
WaitHandle[] waitHandle = new WaitHandle[3]{myResult1.AsyncWaitHandle,myResult2.AsyncWaitHandle,myResult3.AsyncWaitHandle};
/*
try
{
//等待三个异步方法中的至少一个执行完成,才继续执行下面的语句
WaitHandle.WaitAny(waitHandle);
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
*/
myResult1.AsyncWaitHandle.WaitOne(); //如果当前异步方法还没有完成,此异步方法执行完毕才往下执行
myResult2.AsyncWaitHandle.WaitOne();
myResult3.AsyncWaitHandle.WaitOne();
/*
myResult1.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1),false); //如果当前异步方法还没有完成,则等待一秒的时间执行此方法; 如果一秒后此方法还未完成的话,则不再等待,继续往下执行
myResult2.AsyncWaitHandle.WaitOne();
myResult3.AsyncWaitHandle.WaitOne();
*/
Console.WriteLine("测试等待句柄"); //标记语句用.
Console.Read();
}
}
}
(四)线程--使用线程回调方法
(一).描述
此示例演示使用线程回调方法
(二).代码
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace 回调
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//调用的方法
public static string MyMethod()
{
//Console.WriteLine(System.Threading.Thread.CurrentThread.IsBackground);
for(int i = 0;i < 3; i++) //延长时间(模拟实际任务)
{
Thread.Sleep(1000);
}
return "Hello Word";
}
//声明委托,调用MyMethod
private static MyMethodDelegate d = new MyMethodDelegate(MyClass.MyMethod);
//声明委托,调用AsyncCallbackMethod
private static System.AsyncCallback a = new System.AsyncCallback(MyClass.AsyncCallbackMethod);
[STAThread]
static void Main(string[] args)
{
d.BeginInvoke(a,null);
Console.ReadLine(); //这句不能去掉,否则主线程执行完成后,子线会会强迫调用Abort()方法销毁掉,也就执行不到回调方法了
}
public static void AsyncCallbackMethod(System.IAsyncResult myIAsyncResult)
{
string strEnd = d.EndInvoke(myIAsyncResult); //委托调用的方法已经完成,输出其值
Console.WriteLine(strEnd);
Console.Read();
}
}
}
(五)线程--定制线程及设置和获取线程的优先级别
(一).描述
此示例演示怎样定制一个线程,并且设置线程的主要属性和获取线程运行时的状态
(二).代码
using System;
using System.Threading;
namespace 定制线程
{
//委托声明(函数签名)
//delegate string MyMethodDelegate();
class MyClass
{
public static void Method1()
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method1 at :" + i.ToString());
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
Console.WriteLine(" IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");
//是否是后台进程
Console.WriteLine(" IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");
//线程名称
Console.WriteLine(" Name is " + Thread.CurrentThread.Name.ToString()+" ");
//优先级
Console.WriteLine(" Priority is " + Thread.CurrentThread.Priority.ToString()+" ");
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
Console.WriteLine(" ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");
DelayTime(1); //延长时间,模拟执行任务
}
}
public static void Method2()
{
int i;
for(i=0;i<10;i++)
{
Console.Write("Method2 at :" + i.ToString());
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
Console.WriteLine(" IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");
//是否是后台进程
Console.WriteLine(" IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");
//线程名称
Console.WriteLine(" Name is " + Thread.CurrentThread.Name.ToString()+" ");
//优先级
Console.WriteLine(" Priority is " + Thread.CurrentThread.Priority.ToString()+" ");
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
Console.WriteLine(" ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");
DelayTime(1); //延长时间,模拟执行任务
}
}
private static void DelayTime(int n)
{
DateTime startTime = DateTime.Now;
while(startTime.AddSeconds(n) > DateTime.Now)
{
//延长时间,模拟实际中的进程
}
}
[STAThread]
static void Main(string[] args)
{
// MyMethodDelegate d1 = new MyMethodDelegate(MyClass.Method1);
// MyMethodDelegate d2 = new MyMethodDelegate(MyClass.Method2);
Thread thread1 = new Thread(new ThreadStart(Method1));
thread1.Name = "A"; //给线程定义名称
//ThreadPriority枚举共五种优先级,由高->低依次为: Highest->AboveNormal->Normal->BelowNormal->Lowest
//优先级高的先优先执行,相同优先级的线程具有相同对CPU争夺权力
thread1.Priority = ThreadPriority.Highest;
Thread thread2 = new Thread(new ThreadStart(Method2));
thread2.Name = "B";
thread2.Priority = ThreadPriority.Normal;
thread1.Start();
thread2.Start();
Console.Read();
}
}
}
(六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)
(一).描述
此示例演示分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)
(二).代码
using System;
using System.Threading;
using System.Collections;
namespace 加锁_实现临界区互斥操作_
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
private static ArrayList arrList = new ArrayList();
private static int i = 0;
public static void Add()
{
//方法一:用 lock 实现
// lock(arrList)
// {
// arrList.Add(i.ToString());
// i++;
// }
//方法二: 用Interlicked类实现
// System.Threading.Interlocked.Increment(ref i);
// arrList.Add(i.ToString());
//方法三: 用Monitor类实现
try
{
//I.不限时间
//stem.Threading.Monitor.Enter(arrList);
//II.在指定时间获得排他锁
if(System.Threading.Monitor.TryEnter(arrList,TimeSpan.FromSeconds(30))) //在30秒内获取对象排他锁. 灵活运用可以实现防止死锁功能
{ //避免互相等待情况。 在一定时间内得不到排他锁,可能是自己
//占用其它排它锁造成的(别的正在等自己正占用的排它锁,而处于等待状态),
//这时可以释放掉自己正占用的排他锁后,再试图去得到想要的对象的排他锁
arrList.Add(i.ToString());
i++;
}
}
catch
{
//发生异常后自定义错误处理代码
}
finally
{
Monitor.Exit(arrList); //不管是正常还是发生错误,都得释放对象
}
}
[STAThread]
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Add));
Thread thread2 = new Thread(new ThreadStart(Add));
Thread thread3 = new Thread(new ThreadStart(Add));
thread1.Start();
thread2.Start();
thread3.Start();
Console.Read();
for(int i=0;i<arrList.Count;i++)
{
Console.WriteLine(arrList[i].ToString());
}
Console.Read();
}
}
}
(七)线程--管理线程(使线程中止,暂停,挂起等)
(一).描述
此示例演示怎样设置线程的状态(中止,暂停,挂起等)
(二).代码
using System;
using System.Threading;
namespace 管理线程_使线程中止_暂停_挂起等_
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
public static void Method1()
{
//thread1.Abort();一句中的 Abort会引发异常System.Threading.ThreadAbortException,其异常作用,下面会讲解
try
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method1 at :" + i.ToString());
DelayTime(1); //延长时间(模拟执行任务)
}
}
catch(System.Threading.ThreadAbortException)
{
//注意一点,线程跳出此语句块后才终止。
//这里可以写释放此进程占用的资源代码,或者其它一些操作,比如: 在进程结束前将重要数据写回数据库中
Console.WriteLine("进程1马上将被强制杀死!");
Thread.ResetAbort(); //取消Abort()操作,我在这里加这句没用,反而出现异常了,读者如果知道,请告诉我怎样写才对
}
}
public static void Method2()
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method2 at :" + i.ToString());
DelayTime(1); //延长时间,模拟执行任务
}
}
private static void DelayTime(int n)
{
DateTime startTime = DateTime.Now;
while(startTime.AddSeconds(n) > DateTime.Now)
{
//延长时间,模拟实际中的进程
}
}
[STAThread]
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Method1));
Thread thread2 = new Thread(new ThreadStart(Method2));
thread1.Start();
thread2.Start();
thread1.Abort(); //将线程强制终止(杀死)
//thread1.Join的作用是无限制等待thread1终止后,才执行下面的语句,起到与主线程同步的作用.
//原因是: thread1最终是被终止的,但是thread1一个独立的线程,它并不会马上被终止。
//什么时候用:就拿这里来举例吧,当thread1占用着一个资源,当thread1终止后,
//thread2线程马上也要用此资源,这就要求等待thread1彻底终止并释放后占用资源后,才能接着执行下一句,
//否则线程thread2会找不到此资源,甚至会发生异常错误! 为了安全起见,一般是要在Abort()方法后面紧跟一个Join()方法的.
//thread1.Suspend();//此方法将线程无限制时间的挂起,相当于无限制时间的暂停线程
//thread1.Resume(); //将正在挂起的进程继续执行
//Thread.Sleep(1000);//暂停线程1秒钟,以毫秒为单位暂停.
//Thread.ResetAbort(); //取消Abort()操作
//thread1.Interrupt(); //中止线程现在处的状态。如果线程由运行转到休眠,执行此句后,会使线程重新返回到运行状态
Console.Read();
}
}
}
(八)线程--借助 封装类 实现“线程调用带参方法”
(一).描述
由于线程只能执行无参数方法. 有时候需要线程执行"带参数方法"
此示例演示怎样借助封装类实现“线程调用带参方法”
(二).代码
using System;
using System.Threading;
namespace 借助封装类实现_线程调用带参方法_
{
class Help
{
public int x = 0; //乘数1
public int y = 0; //乘数2
public int end = 0; //存放结果
}
class MyClass
{
public static Help myHelp = new Help();
[STAThread]
static void Main(string[] args)
{
//给类的成员赋值
myHelp.x = 5;
myHelp.y = 10;
Thread thread = new Thread(new ThreadStart(GetAccumulate));
thread.Start();
Thread.Sleep(1000); //主线程等待子线程计算完成,否则取得的值为默认值 : 0
Console.WriteLine("两数乘积结果为: "+myHelp.end.ToString());
Console.Read();
}
///
/// 得到两个整数的集
///
/// 乘数x
/// 乘数y
/// x*y
public static void GetAccumulate()
{
myHelp.end = myHelp.x * myHelp.y;
}
}
}
线程是程序执行的基本原子单位. 一个进程可以由多个线程组成.
在分布式编程中,正确使用线程能够很好的提高应用程序的性能及运行效率.
实现原理是将一个进程分成多个线程,然后让它们并发异步执行,来提高运行效率.
并发执行并不是同时执行(占有CPU),任意时刻还是只能有一个线程占用CPU,
只不过是它们争夺CPU频繁一些,感觉到他们似乎都在运行.
下面通过一个简单的例子来说明一下它的工作原理
设一个进程要完成两个任务:任务1和任务2
并且任务1要经历: A1->B1->C1三个步骤才能完成
任务2要经历: A2->B2->C2三个步骤才能完成
I.如果两个任务同步执行的话完成两个任务是这样执行的:
花费时间段: 1 2 3 4 5 6
A1->B1->C1->A2->B2-C2
这样从A1一直到c2只能一个一个地执行. 当A1占用CPU执行时,从B1到C2线程只能在等待.
甚至它们不相互竞争同一个资源时,也要等待前面的执行完成,自己才能执行
II.如果两个任务异步执行的话完成两个任务是这样执行的:
花费时间段: 1 2 3 4 5 6
A1->B1->C1
A2->B2->C2
这样,任务1和任务2就分成两个独立的执行对象. 也就是说:
A1->B1->C1 和 A2->B2->C2 是并发执行的. 当A1在执行某个运算时,A2线程可以去做其它
的一些事情,比如访问磁盘等外部设备等
对比一下I和II两种执行方式,完成所有任务I需要6个时间段,
而II只需要3个时间段就完成了(事实上会多一点,因为方式II中的线程轮询CPU比较频繁,在轮询CPU时会花费一些时间);方式II所需时间是I的一半. 所以II完成整个任务要快.
另一方面,II执行方式,完成每个任务所需的时间可能会花费时间长些,因为I方式是各个线程依次占用CPU执行,当A1占用CPU时,CPU就只为A1服务,当A1执行完后,才让出CPU。II情况就不一样了,它们是异步执行的,轮流使用CPU频繁,经常让出或占有CPU,执行每个线程完成的时间也就会相对长些.
一般情况下,如果多个线程在执行时都要抢占某一个资源或某几个资源,则最好不用异步线程执行.因为它们是并发执行,很可能同时争夺某个资源有CPU,这时要么执行资源分配算法(比如要判断哪个线程优先级高,这要花费时间),或者是按时间片算法(这样要付出 轮询CUP/交接/让出CPU 所需的时间). 如果多个线程所需要的系统资源是比较均匀的,这时完全可以让它们异步并发执行,比如: 当一个线程在给客户端
发出消息后,并不是一直在等待此客户端回应,它可以继续处理下一个客户端请求.
(二)线程--通过委托异步调用方法
(一).描述
先运行个简单的线程示例,认识一下线程
通过委托调用方法,以及使用AsyncResult判断线程的状态
(二).代码
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace 通过委托异步调用方法
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//要调用的动态方法
public string MyMethod1()
{
return "Hello Word1";
}
//要调用的静态方法
public static string MyMethod2()
{
return "Hello Word2";
}
}
class Class1
{
///
/// 应用程序的主入口点。
///
[STAThread]
static void Main(string[] args)
{
MyClass myClass = new MyClass();
//方式1: 声明委托,调用MyMethod1
MyMethodDelegate d = new MyMethodDelegate(myClass.MyMethod1);
string strEnd = d();
Console.WriteLine(strEnd);
//方式2: 声明委托,调用MyMethod2 (使用AsyncResult对象调用)
d = new MyMethodDelegate(MyClass.MyMethod2); //定义一个委托可以供多个方法使用
AsyncResult myResult; //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
myResult = (AsyncResult)d.BeginInvoke(null,null); //开始调用
while(!myResult.IsCompleted) //判断线程是否执行完成
{
Console.WriteLine("正在异步执行MyMethod2 ..");
}
Console.WriteLine("方法MyMethod2执行完成!");
strEnd = d.EndInvoke(myResult); //等待委托调用的方法完成,并返回结果
Console.WriteLine(strEnd);
Console.Read();
}
}
}
(三)线程--等待句柄
(一).描述
本示例代码实现线程等待等待执行,比如一个线程在执行之前要等待所有其它线程或某个线程
先执行完成,或者等待其它线程至少一个执行完成.
(二).代码
using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace 等待句柄
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//要调用方法1
public string Write1()
{
for(double i = 0; i < 100000000000;i++) //此数值大小可以根据自己的环境修改,
//目的是让此方法延长时间而已
{
//延长时间(模拟实际任务)
}
Console.WriteLine("执行方法1");
return "";
}
//要调用方法2
public string Write2()
{
Console.WriteLine("执行方法2");
return "22222222222222";
}
//要调用方法3
public string Write3()
{
Console.WriteLine("执行方法3");
return "33333333333333";
}
[STAThread]
static void Main(string[] args)
{
MyClass myClass = new MyClass();
MyMethodDelegate d1 = new MyMethodDelegate(myClass.Write1);
MyMethodDelegate d2 = new MyMethodDelegate(myClass.Write2);
MyMethodDelegate d3 = new MyMethodDelegate(myClass.Write3);
AsyncResult myResult1,myResult2,myResult3; //此类封闭异步委托异步调用的结果,通过AsyncResult得到结果.
myResult1 = (AsyncResult)d1.BeginInvoke(null,null); //调用
myResult2 = (AsyncResult)d2.BeginInvoke(null,null);
myResult3 = (AsyncResult)d3.BeginInvoke(null,null);
//建立WaitHandle数组对象
WaitHandle[] waitHandle = new WaitHandle[3]{myResult1.AsyncWaitHandle,myResult2.AsyncWaitHandle,myResult3.AsyncWaitHandle};
/*
try
{
//等待三个异步方法中的至少一个执行完成,才继续执行下面的语句
WaitHandle.WaitAny(waitHandle);
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
*/
myResult1.AsyncWaitHandle.WaitOne(); //如果当前异步方法还没有完成,此异步方法执行完毕才往下执行
myResult2.AsyncWaitHandle.WaitOne();
myResult3.AsyncWaitHandle.WaitOne();
/*
myResult1.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1),false); //如果当前异步方法还没有完成,则等待一秒的时间执行此方法; 如果一秒后此方法还未完成的话,则不再等待,继续往下执行
myResult2.AsyncWaitHandle.WaitOne();
myResult3.AsyncWaitHandle.WaitOne();
*/
Console.WriteLine("测试等待句柄"); //标记语句用.
Console.Read();
}
}
}
(四)线程--使用线程回调方法
(一).描述
此示例演示使用线程回调方法
(二).代码
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace 回调
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
//调用的方法
public static string MyMethod()
{
//Console.WriteLine(System.Threading.Thread.CurrentThread.IsBackground);
for(int i = 0;i < 3; i++) //延长时间(模拟实际任务)
{
Thread.Sleep(1000);
}
return "Hello Word";
}
//声明委托,调用MyMethod
private static MyMethodDelegate d = new MyMethodDelegate(MyClass.MyMethod);
//声明委托,调用AsyncCallbackMethod
private static System.AsyncCallback a = new System.AsyncCallback(MyClass.AsyncCallbackMethod);
[STAThread]
static void Main(string[] args)
{
d.BeginInvoke(a,null);
Console.ReadLine(); //这句不能去掉,否则主线程执行完成后,子线会会强迫调用Abort()方法销毁掉,也就执行不到回调方法了
}
public static void AsyncCallbackMethod(System.IAsyncResult myIAsyncResult)
{
string strEnd = d.EndInvoke(myIAsyncResult); //委托调用的方法已经完成,输出其值
Console.WriteLine(strEnd);
Console.Read();
}
}
}
(五)线程--定制线程及设置和获取线程的优先级别
(一).描述
此示例演示怎样定制一个线程,并且设置线程的主要属性和获取线程运行时的状态
(二).代码
using System;
using System.Threading;
namespace 定制线程
{
//委托声明(函数签名)
//delegate string MyMethodDelegate();
class MyClass
{
public static void Method1()
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method1 at :" + i.ToString());
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
Console.WriteLine(" IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");
//是否是后台进程
Console.WriteLine(" IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");
//线程名称
Console.WriteLine(" Name is " + Thread.CurrentThread.Name.ToString()+" ");
//优先级
Console.WriteLine(" Priority is " + Thread.CurrentThread.Priority.ToString()+" ");
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
Console.WriteLine(" ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");
DelayTime(1); //延长时间,模拟执行任务
}
}
public static void Method2()
{
int i;
for(i=0;i<10;i++)
{
Console.Write("Method2 at :" + i.ToString());
//当线程停止/失败或未启动时IsAlive值为:false,否则为:true;
Console.WriteLine(" IsAlive is " + Thread.CurrentThread.IsAlive.ToString()+" ");
//是否是后台进程
Console.WriteLine(" IsBackGround is " + Thread.CurrentThread.IsBackground.ToString()+" ");
//线程名称
Console.WriteLine(" Name is " + Thread.CurrentThread.Name.ToString()+" ");
//优先级
Console.WriteLine(" Priority is " + Thread.CurrentThread.Priority.ToString()+" ");
//ThreadState值组合,有:启动/运行/等待/是否是后台线程等状态. 通过此属性来判断该线程是否完成任务.
Console.WriteLine(" ThreadState is " + Thread.CurrentThread.ThreadState.ToString()+"\n\n ");
DelayTime(1); //延长时间,模拟执行任务
}
}
private static void DelayTime(int n)
{
DateTime startTime = DateTime.Now;
while(startTime.AddSeconds(n) > DateTime.Now)
{
//延长时间,模拟实际中的进程
}
}
[STAThread]
static void Main(string[] args)
{
// MyMethodDelegate d1 = new MyMethodDelegate(MyClass.Method1);
// MyMethodDelegate d2 = new MyMethodDelegate(MyClass.Method2);
Thread thread1 = new Thread(new ThreadStart(Method1));
thread1.Name = "A"; //给线程定义名称
//ThreadPriority枚举共五种优先级,由高->低依次为: Highest->AboveNormal->Normal->BelowNormal->Lowest
//优先级高的先优先执行,相同优先级的线程具有相同对CPU争夺权力
thread1.Priority = ThreadPriority.Highest;
Thread thread2 = new Thread(new ThreadStart(Method2));
thread2.Name = "B";
thread2.Priority = ThreadPriority.Normal;
thread1.Start();
thread2.Start();
Console.Read();
}
}
}
(六)线程--分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)
(一).描述
此示例演示分别用lock以及Interlocked和Monitor类实现线程的临界区操作(互斥)
(二).代码
using System;
using System.Threading;
using System.Collections;
namespace 加锁_实现临界区互斥操作_
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
private static ArrayList arrList = new ArrayList();
private static int i = 0;
public static void Add()
{
//方法一:用 lock 实现
// lock(arrList)
// {
// arrList.Add(i.ToString());
// i++;
// }
//方法二: 用Interlicked类实现
// System.Threading.Interlocked.Increment(ref i);
// arrList.Add(i.ToString());
//方法三: 用Monitor类实现
try
{
//I.不限时间
//stem.Threading.Monitor.Enter(arrList);
//II.在指定时间获得排他锁
if(System.Threading.Monitor.TryEnter(arrList,TimeSpan.FromSeconds(30))) //在30秒内获取对象排他锁. 灵活运用可以实现防止死锁功能
{ //避免互相等待情况。 在一定时间内得不到排他锁,可能是自己
//占用其它排它锁造成的(别的正在等自己正占用的排它锁,而处于等待状态),
//这时可以释放掉自己正占用的排他锁后,再试图去得到想要的对象的排他锁
arrList.Add(i.ToString());
i++;
}
}
catch
{
//发生异常后自定义错误处理代码
}
finally
{
Monitor.Exit(arrList); //不管是正常还是发生错误,都得释放对象
}
}
[STAThread]
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Add));
Thread thread2 = new Thread(new ThreadStart(Add));
Thread thread3 = new Thread(new ThreadStart(Add));
thread1.Start();
thread2.Start();
thread3.Start();
Console.Read();
for(int i=0;i<arrList.Count;i++)
{
Console.WriteLine(arrList[i].ToString());
}
Console.Read();
}
}
}
(七)线程--管理线程(使线程中止,暂停,挂起等)
(一).描述
此示例演示怎样设置线程的状态(中止,暂停,挂起等)
(二).代码
using System;
using System.Threading;
namespace 管理线程_使线程中止_暂停_挂起等_
{
//委托声明(函数签名)
delegate string MyMethodDelegate();
class MyClass
{
public static void Method1()
{
//thread1.Abort();一句中的 Abort会引发异常System.Threading.ThreadAbortException,其异常作用,下面会讲解
try
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method1 at :" + i.ToString());
DelayTime(1); //延长时间(模拟执行任务)
}
}
catch(System.Threading.ThreadAbortException)
{
//注意一点,线程跳出此语句块后才终止。
//这里可以写释放此进程占用的资源代码,或者其它一些操作,比如: 在进程结束前将重要数据写回数据库中
Console.WriteLine("进程1马上将被强制杀死!");
Thread.ResetAbort(); //取消Abort()操作,我在这里加这句没用,反而出现异常了,读者如果知道,请告诉我怎样写才对
}
}
public static void Method2()
{
int i;
for(i=0;i<10;i++)
{
Console.WriteLine("Method2 at :" + i.ToString());
DelayTime(1); //延长时间,模拟执行任务
}
}
private static void DelayTime(int n)
{
DateTime startTime = DateTime.Now;
while(startTime.AddSeconds(n) > DateTime.Now)
{
//延长时间,模拟实际中的进程
}
}
[STAThread]
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(Method1));
Thread thread2 = new Thread(new ThreadStart(Method2));
thread1.Start();
thread2.Start();
thread1.Abort(); //将线程强制终止(杀死)
//thread1.Join的作用是无限制等待thread1终止后,才执行下面的语句,起到与主线程同步的作用.
//原因是: thread1最终是被终止的,但是thread1一个独立的线程,它并不会马上被终止。
//什么时候用:就拿这里来举例吧,当thread1占用着一个资源,当thread1终止后,
//thread2线程马上也要用此资源,这就要求等待thread1彻底终止并释放后占用资源后,才能接着执行下一句,
//否则线程thread2会找不到此资源,甚至会发生异常错误! 为了安全起见,一般是要在Abort()方法后面紧跟一个Join()方法的.
//thread1.Suspend();//此方法将线程无限制时间的挂起,相当于无限制时间的暂停线程
//thread1.Resume(); //将正在挂起的进程继续执行
//Thread.Sleep(1000);//暂停线程1秒钟,以毫秒为单位暂停.
//Thread.ResetAbort(); //取消Abort()操作
//thread1.Interrupt(); //中止线程现在处的状态。如果线程由运行转到休眠,执行此句后,会使线程重新返回到运行状态
Console.Read();
}
}
}
(八)线程--借助 封装类 实现“线程调用带参方法”
(一).描述
由于线程只能执行无参数方法. 有时候需要线程执行"带参数方法"
此示例演示怎样借助封装类实现“线程调用带参方法”
(二).代码
using System;
using System.Threading;
namespace 借助封装类实现_线程调用带参方法_
{
class Help
{
public int x = 0; //乘数1
public int y = 0; //乘数2
public int end = 0; //存放结果
}
class MyClass
{
public static Help myHelp = new Help();
[STAThread]
static void Main(string[] args)
{
//给类的成员赋值
myHelp.x = 5;
myHelp.y = 10;
Thread thread = new Thread(new ThreadStart(GetAccumulate));
thread.Start();
Thread.Sleep(1000); //主线程等待子线程计算完成,否则取得的值为默认值 : 0
Console.WriteLine("两数乘积结果为: "+myHelp.end.ToString());
Console.Read();
}
///
/// 得到两个整数的集
///
/// 乘数x
/// 乘数y
///
public static void GetAccumulate()
{
myHelp.end = myHelp.x * myHelp.y;
}
}
}