net 多线程

概念

进程:计算机概念,程序运行在服务器占据的全部计算机的资源
线程:计算机概念,是进程在相应操作时候的一个最小单元,也包括cpu/硬盘/内存 虚拟概念
进程和线程:包含关系,线程是属于某一个进程的,如果一个进程销毁,线程也就不会存在。
句柄:描述程序中的某一个最小单元,是一个long数字,操作系统通过这个数字识别应用程序。,一个程序 的ID,或者说一个控件的ID
多线程:计算概念,就是某一个进程中,多个线程同时运行;

 C#中的多线程:
Thread类是C#语言对线程对象一个封装;

 为什么可以多线程呢?
1、CPU有多个核;可以并行计算;
双核四线:这里的线程是模拟核;
 2、cpu分片:某1s的处理能切分成1000份,操作系统调度去相应不同的任务;
从宏观角度来说:感觉就有多个任务在并发执行;
从微观角度来说:一个物理cpu不能在某一刻为某一个任务服务

同步异步:
 同步方法:发起调用,只有在调用的方法完成以后,才能继续执行一下一行代码,按照顺序执行;
 诚心请吃饭,我请你吃饭,你说你现在需要忙一会儿,我等你,等你忙完了以后,咱们一起去吃饭。
 异步方法:发起调用,不等待完成,直接进入下一行代码的执行,启动一个新的线程来完成计算
 客气一下请人吃饭:我请你吃饭,你说你现在需要忙一会儿,我就不等你了,我自己先去吃饭了,你忙完以后,自己去吃饭。


 1、同步方法卡界面:主线线程(UI线程)忙于计算,无暇他顾
 异步方法不卡界面:因为异步方法是新启动一个线程去完后计算,主线程闲置
改善用户体验,winform程序点击某一个按钮,不会卡死界面;
发短信,发邮件可以交给一个子线程去完成

 2、同步方法执行慢:只有一个线程完成计算
异步方法执行快:多个线程去完成计算
 10000ms 3000ms 快了三倍多
20000ms 15000ms cpu密集型计算
 资源换性能

3、同步方法有序执行,异步多线程无顺序
启动无序,线程资源是向操作系统申请的,操作系统有自己的调度策略,所以启动是随机的;
以上两点得出: 结束也是没有顺序

/如果需要控制顺序呢?怎么实现?

 回调:把后续的动作通过回调参数传递进去,子线程完成计算以后,去嗲用这个回调委托

 

一、Thread

Thread.CurrentThread.ManagedThreadId.ToString("00") ;  //当前线程id

Thread.Sleep(2000);//线程等待

二、委托 

委托可以理解为一种协议。委托,是什么意思呢?举个例子,你碰到一件事,你需要让别人来帮你做(可能你还有别的事情要做),这就是委托,把你现在不能做的事让别人去做。为什么说委托就像一个协议呢,因为你不想把事情搞砸了,所以你“委托”的这个人做的这件事,你需要给他定一个标准。在C#中就是给所委托的对象定义好签名,参数有几个,分别是什么类型,委托方法需要反馈给你什么东西(或者不反馈)。

C#的委托调用有以下2种方法:

  1、BeinInvoke => 异步调用,EndInvoke => 获得异步调用的返回值(方法没执行完毕之前会一直阻塞);

  在C#中,任何涉及BeginXXX与EndXXX名字的方法都是异步。

  2、Invoke => 同步调用;

  在Control中用以上2种方法都会造成界面假死,因为这是UI线程。  

我们知道 beginvoke就是通过线程的调用来异步的完成一些工作。一般只需要启动它就好,让它一直操作着。例如 用begininvoke修改界面显示,那么就是每次有所变化时它自动的改变界面的显示,因为它在后台执行着。 

但是有时候我们需要知道它的结束信息,并且在结束时还有所安排。这时候就需要endinvoke了 

C#如何使用异步编程【BeginInvoke/EndInvoke】

1、Action 委托

  1. Action委托至少0个参数,至多16个参数,无返回值。
  2. Action 表示无参,无返回值的委托。
  3. Action<int,string> 表示有传入参数int,string无返回值的委托。
  4. Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托。
  5. Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托。
            IAsyncResult asyncResult = null;
            AsyncCallback callback = ar =>
            {

                Thread.Sleep(5000);
                Console.WriteLine($"这里是beginInvoke的第三个参数{ar.AsyncState}");
                Console.WriteLine(object.ReferenceEquals(ar, asyncResult));
                Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss.fff")}");
                Console.WriteLine("计算结束");
            };
            {
                //1、回调
                Action<string> action = this.DoSomethingLong;
                //如果把自定义的参数传入到回调函数中去?
                asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "八万公里");
                Console.WriteLine("计算结束");
            }
//几种等待
            //2、IsCompleted 完成等待 
            {
                int i = 0;
                while (!asyncResult.IsCompleted)
                {
                    if (i < 9)
                    {
                        Console.WriteLine($"正在玩命为你加载中。。。已经完成{++i * 10}%");
                    }
                    else
                    {
                        Console.WriteLine($"正在玩命为你加载中。。。已经完成99.9999%");
                    }
                    Thread.Sleep(200);
                }

                Console.WriteLine("加载完成。。。");
            }

            //以上两种都是为了等待任务的完成;
            //3、WaitOne等待
            asyncResult.AsyncWaitHandle.WaitOne();//一直等待任务完成
            asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
            asyncResult.AsyncWaitHandle.WaitOne(3000);//最多等待3000ms,如果超时了,就不等待了 

            {
                //4、EndInvoke也可以等待,可以获取委托返回值
                Func<int> func = () =>
                {
                    //Thread.Sleep(5000);
                    return DateTime.Now.Year;
                };
                func.Invoke();
                IAsyncResult asyncResult1 = func.BeginInvoke(ar =>
                  {
                      func.EndInvoke(ar);
                  }, null);

                int iResult = func.EndInvoke(asyncResult1);
                Console.WriteLine(iResult);

            }

 

技巧

c# Task返回值

Task返回值,目前有2种情况,一种是异步async返回值,一种是同步返回值

第一种:异步返回值

Task方法如果加了async关键字,那么就是异步返回方法,如果是异步返回方法,需要返回一个值时,直接return value,就可以了。

第二种:同步返回值

Task方法如果没有加async关键字,需要返回一个值时,使用Task.FromResult方法,Task.FromResult(value)就可以了。

posted on 2023-08-08 10:42  michellexiaoqi  阅读(31)  评论(0编辑  收藏  举报