本系列将和大家分享.Net中的异步和多线程,本文主要介绍的是Thread和ThreadPool类。

一、Thread类

C#里面的多线程:Thread类是C#语言对线程对象的一个封装。

首先看下如何开启线程,执行委托的内容:

/// <summary>/// 一个比较耗时耗资源的私有方法/// </summary>private void DoSomethingLong(string name){ Console.WriteLine($"****************DoSomethingLong Start {name} {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +  $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); long lResult = 0; for (int i = 0; i < 1_000_000_000; i++) {  lResult += i; } Thread.Sleep(2000); Console.WriteLine($"****************DoSomethingLong End {name} {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +  $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");}

/// <summary>/// 多线程 Thread类是.NET Framework 1.0的时候出现的/// Thread:C#对线程对象的一个封装/// </summary>private void btnThread_Click(object sender, EventArgs e){ Console.WriteLine($"****************btnThread_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +  $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); {  ParameterizedThreadStart method = o => this.DoSomethingLong("btnThread_Click");  Thread thread = new Thread(method);  thread.Start("浪子天涯");//开启线程,执行委托的内容 } Console.WriteLine($"****************btnThread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +  $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");}

线程等待、线程优先级、前台线程和后台线程:

{ ThreadStart method = () => {  Thread.Sleep(5000);  this.DoSomethingLong("btnThread_Click");  Thread.Sleep(5000); }; Thread thread = new Thread(method); thread.Start(); //开启线程,执行委托的内容 //该花括号内的这些方法已经被微软抛弃了,建议不要去用 {  //thread.Suspend(); //暂停  //thread.Resume();//恢复 真的不该要的,暂停不一定马上暂停;让线程操作太复杂了  //thread.Abort();  //线程是计算机资源,程序想停下线程,只能向操作系统通知(线程抛异常),  //会有延时/不一定能真的停下来  //Thread.ResetAbort(); } //1等待 while (thread.ThreadState != ThreadState.Stopped) {  Thread.Sleep(200); //当前线程休息200ms } //2 Join等待 thread.Join(); //运行这句代码的线程,等待thread的完成 thread.Join(1000); //最多等待1000ms Console.WriteLine("这里是线程执行完之后才操作。。。"); //最高优先级:优先执行,但不代表优先完成看,甚至说极端情况下,还有意外发生,不能通过这个来控制线程的执行先后顺序 thread.Priority = ThreadPriority.Highest; //是否是后台线程 默认是false thread.IsBackground = false; //默认是false 前台线程,进程关闭,线程需要计算完后才退出 //thread.IsBackground = true;//关闭进程,线程退出}

下面来看下Thread类的使用:

基于Thread封装一个带有回调的

/// <summary>/// 基于Thread封装一个回调/// 回调:启动子线程执行动作A--不阻塞--A执行完后子线程会执行动作B/// </summary>/// <param name="threadStart">多线程执行的操作</param>/// <param name="actionCallback">线程完成后,回调的动作</param>private void ThreadWithCallBack(ThreadStart threadStart, Action actionCallback){ //Thread thread = new Thread(threadStart); //thread.Start(); //thread.Join(); //错了,因为方法被阻塞了 //actionCallback.Invoke(); ThreadStart method = new ThreadStart(() => {  threadStart.Invoke();  actionCallback.Invoke(); }); new Thread(method).Start();}

{ ThreadStart threadStart = () => this.DoSomethingLong("btnThread_Click"); Action actionCallBack = () => {  Thread.Sleep(2000);  Console.WriteLine($"This is Calllback {Thread.CurrentThread.ManagedThreadId.ToString("00")}"); }; this.ThreadWithCallBack(threadStart, actionCallBack);}

基于Thread封装一个带有返回值的

/// <summary>/// 基于Thread封装一个带有返回值的/// 1 异步,非阻塞的/// 2 还能获取到最终计算结果/// /// 既要不阻塞,又要计算结果?不可能!故此处返回一个委托,当外部需要使用结果的时候再阻塞,此时可能已经计算完了。/// </summary>private Func<T> ThreadWithReturn<T>(Func<T> func){ T t = default(T); ThreadStart threadStart = new ThreadStart(() => {  t = func.Invoke(); }); Thread thread = new Thread(threadStart); thread.Start(); return new Func<T>(() => {  thread.Join();  //thread.ThreadState  return t; });}

{ Func<int> func = () => {  Thread.Sleep(5000);  return DateTime.Now.Year; }; Func<int> funcThread = this.ThreadWithReturn(func);//非阻塞 Console.WriteLine("do something 1"); Console.WriteLine("do something 2"); Console.WriteLine("do something 3"); i.........