多线程
线程的基础知识
2.1 System.Threading.Thread类
System.Threading.Thread是用于控制线程的基础类,通过Thread可以控制当前应用程序域中线程的创建、挂起、停止、销毁。
它包括以下常用公共属性:
属性名称 说明
CurrentContext 获取线程正在其中执行的当前上下文。
CurrentThread 获取当前正在运行的线程。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。
Thread基础类
构造函数参数
ParameterizedThreadStart
start:System.Threading.ParameterizedThreadStart 委托,它表示此线程开始执行时要调用的方法。
ThreadStart
start:System.Threading.ThreadStart 委托,它表示此线程开始执行时要调用的方法。
int
maxStackSize:线程要使用的最大堆栈大小;如果为 0 则使用可执行文件的文件头中指定的默认最大堆栈大小。 重要地,对于部分受信任的代码,如果 maxStackSize 大于默认堆栈大小,则将其忽略。 不引发异常。
Threa类参数
ApartmentState
获取或设置此线程的单元状态。【已经否决】
使用getapartmentstate,setapartmentstate或trysetapartmentstate
CurrentContext
获取线程正在其中执行的当前上下文。
CurrentCulture
获取或设置当前线程的区域性。返回 System.Globalization.CultureInfo
IsAlive
获取一个值,该值指示当前线程的执行状态。bool
IsBackground
获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread
获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId
获取当前托管线程的唯一标识符。
Name
获取或设置线程的名称。
Priority
获取或设置一个值,该值指示线程的调度优先级。
枚举类型
Lowest 安排在具有任何其他优先级的线程之后。
BelowNormal 安排在具有 Normal 优先级的线程之后,在具有 Lowest 优先级的线程之前。
Normal 安排在具有 AboveNormal 优先级的线程之后,在具有 BelowNormal 优先级的线程之前。 默认情况下,线程具有 Normal 优先级
AboveNormal 安排在具有 Highest 优先级的线程之后,在具有 Normal 优先级的线程之前。
Highest 可以将 System.Threading.Thread 安排在具有任何其他优先级的线程之前。
ThreadState
获取一个值,该值包含当前线程的状态。
枚举类型
Running 线程已启动,它未被阻塞,并且没有挂起的
StopRequested 正在请求线程停止。 这仅用于内部。
SuspendRequested 正在请求线程挂起。
Background 线程正作为后台线程执行(相对于前台线程而言)。 此状态可以通过设置 System.Threading.Thread.IsBackground 属性来控制。
Unstarted 尚未对线程调用 System.Threading.Thread.Start() 方法。
Stopped 线程已停止
WaitSleepJoin 线程已被阻止。 这可能是因为:调用 System.Threading.Thread.Sleep(System.Int32) 或 System.Threading.Thread.Join()、请求锁定(例如通过调用System.Threading.Monitor.Enter(System.Object) 或 System.Threading.Monitor.Wait(System.Object,System.Int32,System.Boolean))或等待线程同步对象(例如System.Threading.ManualResetEvent)。
Suspended 线程已挂起。
AbortRequested 已对线程调用了 System.Threading.Thread.Abort(System.Object) 方法,但线程尚未收到试图终止它的挂起的 System.Threading.ThreadAbortException。
Aborted 线程状态包括 System.Threading.ThreadState.AbortRequested 并且该线程现在已死,但其状态尚未更改为 System.Threading.ThreadState.Stopped。
方法
Abort() 在调用此方法的线程上引发 System.Threading.ThreadAbortException,以开始终止此线程的过程。 调用此方法通常会终止线程。
AllocateDataSlot(); 在所有的线程上分配未命名的数据槽
AllocateNamedDataSlot(string name);在所有线程上分配已命名的数据槽。
FreeNamedDataSlot(string name);为进程中的所有线程消除名称与槽之间的关联,释放数据槽
GetDomainID() 返回唯一的应用程序域标识符。
Interrupt();中断处于 WaitSleepJoin 线程状态的线程。
Join();在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。 参数millisecondsTimeout等待线程终止的毫秒数。timeout 设置为等待线程终止的时间量的 System.TimeSpan。(MSDN补充)使用此方法确保线程已终止。 如果线程不终止,则调用方将无限期阻塞。 如果调用 Join 时该线程已终止,此方法将立即返回。
ResetAbort();取消为当前线程请求的 System.Threading.Thread.Abort(System.Object)。
Resume();继续已挂起的线程。避免使用
Sleep(int millisecondsTimeout);将当前线程挂起指定的时间millisecondsTimeout
Sleep(TimeSpan timeout);同上
SpinWait(int iterations);导致线程等待由 iterations 参数定义的时间量。
Start();导致操作系统将当前实例的状态更改为 System.Threading.ThreadState.Running。
Start(object parameter);parameter:一个对象,包含线程执行的方法要使用的数据。
Suspend()挂起线程,或者如果线程已挂起,则不起作用。避免使用
Yield();导致调用线程执行准备好在当前处理器上运行的另一个线程。 由操作系统选择要执行的线程。
Thread.Suspend()与 Thread.Resume()是在Framework1.0 就已经存在的老方法了,它们分别可以挂起、恢复线程。但在Framework2.0中就已经明确排斥这两个方法。这是因为一旦某个线程占用了已有的资源,再使用Suspend()使线程长期处于挂起状态,当在其他线程调用这些资源的时候就会引起死锁!所以在没有必要的情况下应该避免使用这两个方法。
示例程序
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ConsoleAppModel06 { class Program { static void Main(string[] args) { //简单线程的状态显示 //Thread thread = Thread.CurrentThread; //thread.Name = "Main Thread"; //for (int i = 0; i < 10; i++) //{ // string threadMessage = string.Format("唯一标示 Thread ID:{0}\n应用程序域标示符 Current AppDomainId:{1}\n " + // "当前上下文ID Current ContextId:{2}\n当前线程名Thread Name:{3}\n " + // "当前线程的状态Thread State:{4}\n调度优先级Thread Priority:{5}\n", // thread.ManagedThreadId, // Thread.GetDomainID(), // Thread.CurrentContext.ContextID, // thread.Name, // thread.ThreadState, // thread.Priority); // Console.WriteLine(threadMessage); // Console.WriteLine(); //} Console.WriteLine("Thread开始......\n唯一标示 Thread ID:" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(3000); Message mess = new Message(); /*无参数运行方法*/ Thread myt01 = new Thread(new ThreadStart(mess.Print)); /*有参数运行方法*/ Thread myt02 = new Thread(new ParameterizedThreadStart(mess.Print)); myt01.Start(); int p=5; /*传递参数*/ myt02.Start(p); /*主线程打印*/ for (int i = 0; i < 10; i++) { Thread.Sleep(3000); Console.WriteLine("打印打印......"+i.ToString()); } } } class Message { /*无参数*/ public void Print() { Thread.Sleep(3000); Console.WriteLine("方法01 hread 中......"); for (int i = 0; i<10;i++ ) { Thread.Sleep(3000); Console.WriteLine("方法01 打印 " + i.ToString()); Console.WriteLine("方法01 唯一标示 Thread ID:" + Thread.CurrentThread.ManagedThreadId); } } /*有参数*/ public void Print(object o) { int j = (int)o; Thread.Sleep(3000); Console.WriteLine("方法02 Thread 中......"); for (int i = 0; i < j; i++) { Thread.Sleep(3000); Console.WriteLine("方法02 打印 " + i.ToString()); Console.WriteLine("方法02 唯一标示 Thread ID:" + Thread.CurrentThread.ManagedThreadId); } } } }
关于中断线程
在线程Abort()后,会产生ThreadAbortException异常,之后需要调用ResetAbort()取消终止,继续执行线程。ThreadAbortException 是一个可以由应用程序代码捕获的特殊异常,但捕获后除非调用 ResetAbort,否则会在 catch 块的结尾再次引发它。ResetAbort 取消中止请求,并防止 ThreadAbortException 终止该线程。
CLR线程池(ThreadPool)
它是一个静态类,每个进程只有一个线程池
方法如下
BindHandle();将操作系统句柄绑定到 System.Threading.ThreadPool。
参数参数: (IntPtr) osHandle: 持有句柄的 System.IntPtr。 在非托管端必须为重叠 I/O 打开该句柄。SafeHandle osHandle: 保存操作系统句柄的 System.Runtime.InteropServices.SafeHandle。 在非托管端必须为重叠 I/O 打开该句柄。
GetAvailableThreads(out int workerThreads, out int completionPortThreads);方法返回的最大线程池线程数和当前活动线程数之间的差值。
GetMaxThreads(out int workerThreads, out int completionPortThreads);检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
GetMinThreads(out int workerThreads, out int completionPortThreads);发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
QueueUserWorkItem()将方法排入队列以便执行。 此方法在有线程池线程变得可用时执行。参数是一个public delegate void WaitCallback(object state);的委托
SetMaxThreads(int workerThreads, int completionPortThreads);设置可以同时处于活动状态的线程池的请求数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
SetMinThreads(int workerThreads, int completionPortThreads);发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。
示例
//static void Main(string[] args) //{ // //ThreadPool // //设置工作线程数为10 // Console.WriteLine("Thread......"); // ThreadPool.SetMaxThreads(10, 10); // ThreadPool.QueueUserWorkItem(new WaitCallback(Mess));//用QueueUserWorkItem启动工作者线程 // Console.ReadKey(); //} //public static void Mess(object o) //{ // Console.WriteLine("Threading......"); //}
会出现的情况:随机打印Threading......和Thread......,如果注释掉Console.WriteLine("Thread......");
则有可能啥也不打印,然后输入(即执行Console.ReadKey();)结束的时候打印Threading......
原因是线程与线程在宏观上都是并行执行的,没有先后。
示例
static void Main(string[] args) { //ThreadPool //设置工作线程数为100 Console.WriteLine("Thread......"); ThreadPool.SetMaxThreads(10, 10); //用QueueUserWorkItem启动工作者线程,是回调 ThreadPool.QueueUserWorkItem(new WaitCallback(Mess)); ThreadPool.QueueUserWorkItem(new WaitCallback(Message), "123"); //Console.WriteLine("Thread......"); Console.ReadKey(); } public static void Mess(object o) { Console.WriteLine("Threading......"); } public static void Message(object o) { Console.WriteLine("Message Threading......"+o.ToString()); }
委托类包括以下几个重要方法
当调用Invoke()方法时,对应此委托的所有方法都会被执行
BeginInvoke()调用委托方法,EndInvoke()结束异步操作,返回IAsyncResult接口
IAsyncResult接口使用
object AsyncState { get; }
摘要:获取用户定义的对象,它限定或包含关于异步操作的信息。
返回结果:用户定义的对象,它限定或包含关于异步操作的信息。
WaitHandle AsyncWaitHandle { get; }
摘要:获取用于等待异步操作完成的 System.Threading.WaitHandle。
返回结果:用于等待异步操作完成的 System.Threading.WaitHandle。
bool CompletedSynchronously { get; }
摘要:获取一个值,该值指示异步操作是否同步完成。
返回结果:如果异步操作同步完成,则为 true;否则为 false。
bool IsCompleted { get; }
摘要:获取一个值,该值指示异步操作是否已完成。
返回结果:如果操作完成则为 true,否则为 false。
有些地方是学习博客园风尘浪子,
然后自己查漏补缺和理解,在此感谢http://www.cnblogs.com/leslies2