C#多线程编程(二)
时间:2010-09-29 来源:笑清风
一、System.Threading命名空间
1.Thread类
这个类代表了处理器线程,它可以管理线程的优先级、读取线程的状态等。
2.创建线程
3.ThreadStart委托和执行分支
public class ThreadStartBranching
{
enum UserClass
{
ClassAdmin,
ClassUser
}
static void AdminMethod()
{
Console.WriteLine("Admin Method");
}
static void UserMethod()
{
Console.WriteLine("User Method");
}
static void ExecuteFor(UserClass uc)
{
ThreadStart ts;
ThreadStart tsAdmin = new ThreadStart(AdminMethod);
ThreadStart tsUser = new ThreadStart(UserMethod);
if (uc == UserClass.ClassAdmin)
ts = tsAdmin;
else
ts = tsUser;
Thread t = new Thread(ts);
t.Start();
}
static void Main()
{
ExecuteFor(UserClass.ClassAdmin);
ExecuteFor(UserClass.ClassUser);
Console.ReadLine();
}
}
4.线程的属性和方法
public class ThreadState
{
static void WorkerFunction()
{
string ThreadState;
for (int i = 0; i < 50000; i++)
{
if (i % 5000 == 0)
{
ThreadState = Thread.CurrentThread.ThreadState.ToString();
Console.WriteLine("Worker:" + ThreadState);
}
}
Console.WriteLine("Worker Function Complete");
}
static void Main()
{
string ThreadState;
Thread t = new Thread(new ThreadStart(WorkerFunction));
t.Start();
while (t.IsAlive)
{
Console.WriteLine("Still waiting. I am going back to sleep.");
Thread.Sleep(200);
}
ThreadState = t.ThreadState.ToString();
Console.WriteLine("He is finally done! Thread state is :" + ThreadState);
Console.ReadLine();
}
}
5.线程的优先级
public class ThreadPriority2
{
public static Thread worker;
public static Thread worker2;
static void Main()
{
Console.WriteLine("Entering void Main()");
worker = new Thread(new ThreadStart(FindPriority));
worker2 = new Thread(new ThreadStart(FindPriority2));
worker.Name = "FindPriority()Thread";
worker2.Name = "FindPriority()Thread2";
worker2.Priority = System.Threading.ThreadPriority.Highest;
worker.Start();
worker2.Start();
Console.WriteLine("Exiting void Main()");
Console.ReadLine();
}
public static void FindPriority()
{
Console.WriteLine("Name:" + worker.Name);
Console.WriteLine("State:" + worker.ThreadState.ToString());
Console.WriteLine("Priority:" + worker.Priority.ToString());
}
public static void FindPriority2()
{
Console.WriteLine("Name:" + worker2.Name);
Console.WriteLine("State:" + worker2.ThreadState.ToString());
Console.WriteLine("Priority:" + worker2.Priority.ToString());
}
}
6.计时器和回调
线程不像应用程序的其余代码那样按次序运行,所以不能确定发生在线程中影响特定共享资源的动作,是否会在另一个线程中的代码访问同一共享资源之前完成。使用计时器是一种简单的方法,可以按特定的时间间隔执行方法,检查在继续操作之前所要求的动作是否已经完成,这是一个非常简单的模型。
计时器由两个对象组成:TimeCallback和Timer。TimeCallback委托定义了以指定间隔执行的方法,而Timer对象本身就是计时器。TimeCallback将一个特定的方法与计时器联系起来。
public class TimerExample
{
private string message;
private static Timer tmr;
private static bool complete;
public static void Main()
{
TimerExample obj = new TimerExample();
Thread t = new Thread(new ThreadStart(obj.GenerateText));
t.Start();
TimerCallback tmrCallBack = new TimerCallback(obj.GetText);
tmr = new System.Threading.Timer(tmrCallBack,null,TimeSpan.Zero,TimeSpan.FromSeconds(2));
do
{
if(complete)
break;
}while(true);
Console.WriteLine("Exiting Main.....");
Console.ReadLine();
}
public void GenerateText()
{
StringBuilder sb = new StringBuilder();
for (int i = 1; i < 200; i++)
{
sb.Append("This is Line");
sb.Append(i.ToString());
sb.Append(System.Environment.NewLine);
}
message = sb.ToString();
}
public void GetText(object state)
{
if (message == null)
{
Console.WriteLine("....");
return;
}
Console.WriteLine("Message is :");
Console.WriteLine(message);
tmr.Dispose();
complete = true;
}
}
7.使用线程调节线程
使用windows performance monitor 工具,然后添加几个公共语言运行库专用的性能类别就可以查看公共语言运行库中运行的线程。公共语言运行库提供了一种性能计数器类别.Net CLR LocksAndThreads 使用这个类别可以获得CLR托管线程的更多信息。
二、线程的生存期
- Aborted(中止)------线程处于停止状态,但不一定执行完毕。
- AbortRequested(请求中止)------Aborted已被调用,但是线程还没有收到试图终止自己的System.Threading.ThreadAbortexception,也就是说线程还没有停止,但不久就会停止。
- Background(后台)------线程在后台执行。
- Running(运行)------线程已启动,而且没有停止。
- Stopped(停止)------线程已完成了其所有的指令,而且已经停止
- StopRequested(请求停止)------请求停止线程
- Suspended(挂起)------线程处于关起状态
- SuspendRequested(请求挂起)------请求线程挂起
- Unstarted(未启动)------还没有在线程上调用Start()方法
- WaitSleepJoin(等待睡眠连接)------线程已被阻止。通过调用Wait()、Sleep()、Join()方法,来暂停线程。
下图显示线程的生存期:
1.使线程睡眠
Sleep() 第一种重载将一个整数作为参数,指定线程挂起指定的毫秒数;第二种重载是将TimeSpan对象作为参数,并且基于TimeSpan值挂起当前的线程。线程睡眠时其处于WaitSleepJoin状态。
2.中断线程
当线程进入睡眠时,它就进入WaitSleepJoin状态。如果线程处于睡眠状态,在到达指定的睡眠时间之前唤醒线程的唯一方法是使用Interrupt()方法,Interrupt()方法会将线程放回到调度队列中。Interrupt()方法是将处于睡眠状态的线程重新激活的最好方法。
public class ThreadInterrupt
{
public static Thread sleeper;
public static Thread worker;
public static void Main()
{
Console.WriteLine("Entering the void Main!");
sleeper = new Thread(new ThreadStart(SleepingThread));
worker = new Thread(new ThreadStart(AwakeTheThread));
sleeper.Start();
worker.Start();
Console.WriteLine("Exiting the void Main!");
}
public static void SleepingThread()
{
Console.WriteLine("Entering the SleepingThread!");
for (int i = 0; i < 30; i++)
{
Console.WriteLine(i + "");
if (i == 10 || i == 20 || i == 30)
{
Console.WriteLine("Going to sleep at:" + i);
Thread.Sleep(20);
Console.WriteLine("Starting to sleep at:" + i);
}
}
Console.WriteLine("Exiting the SleepingThread!");
}
public static void AwakeTheThread()
{
Console.WriteLine("Entering the AwakeTheThread!");
for (int i = 31; i < 100; i++)
{
Console.WriteLine(i + "");
Console.WriteLine(sleeper.ThreadState.ToString());
if (sleeper.ThreadState == System.Threading.ThreadState.WaitSleepJoin)
{
Console.WriteLine("Interrupting the sleeping thread");
sleeper.Interrupt();
}
}
Console.WriteLine("Exiting the AwakeTheThread!");
}
}
3.暂停及恢复线程
Thread类的Suspend()和Resume()方法可以用来挂起和恢复线程,Suspend()方法将无限期的挂起当前线程,直到另一个线程将其唤醒,调用Suspend()方法时,线程会处于SuspendRequested或Suspended状态。
4.销毁线程
5.连接线程
三、线程不是万能的
四、使用线程的时机
1.后台进程
2.访问外部资源
五、线程的陷阱
1.再次访问的执行顺序
2.循环中的线程











