多线程Task(thread ,threadpool 已经过时)

一、进程:计算机概念,虚拟的记录,   描述一个应用程序在计算机上运行的时候,所消耗的各种资源的集合---Cpu+内容+磁盘IO+网络资源;

二、线程:(计算机资源)一个程序的进程中,所执行的具体的某一个动作的最小执行流;小到点击某个按钮,大到通过网络发送一句话出去;

  具体到某一个人:
       进程必然是包含了多个线程;线程是依附于进程存在的;如果进程不在了,线程也随之消失了;

三、句柄:是一个long了类型的数字,对应这计算机程序中的某一个小部件;要操作程序,对应的最小的单位;
       公司中的任何一个物件  --编号--计算机---会给计算机坐个编号---(部门---座位号)  ====资产处的人员和设备对应表

四、为什么计算机可以多线程?跟计算机的CPU的核数有关;
6核12线程:把六个核心进行逻辑切分:如果有动作需要计算机响应,操作系统就会去申请CPU来处理;CPU在执行动作的时候,CPU是分片执行:
分片:把每一个核每一毫秒可以执行的动作,切分成10000份;操作系统在调度的时候,执行动作,切分后去执行的多个动作的时候;开始动作A,使用的是分片后的某一份; 结束的时候,可能使用的是另外的某一份;
计算机在不断的调度过程中;
1.从宏观角度来说:多个动作,就可以做到在某一段时间内;看似同时执行完毕了;
2.从微观的角度来说:某一时刻,同意时刻只能处理一件事儿--串行执行;

同步方法:

单线程执行代码命令:同步执行;
线性执行,从上往下依次执行--很符合我们人类的思维逻辑,线程ID为01(主线程/UI线程)  同步方法执行慢;卡顿界面--只有一个线程参与计算

异步方法:

多线程执行代码命令:异步执行:
开启了一个新的线程(多线程--子线程)(有一个新的线程Id);且不再是线型执行了; UI线程不等待子线程执行完毕;主线程直接往后执行; 子线程延迟执行

异步方法执行快:不卡顿界面;开启了一个新的线程去执行去了;开启了五个线程去执行动作:消耗的计算机资源多(工钱多)
异步方法--多线程方法--以资源换时间; 使用大量的资源,降低时间成本;
无序执行:线程开启无法控制谁先谁后;线程执行计算结束也无法控制谁先谁后;---多线程异步执行:无序执行;

//在ASP.NET Core的年代:BeginInvoke不再支持了
Action<string> action = this.DoSomething;
AsyncCallback asyncCallback = null;
action.BeginInvoke(" Seven ", asyncCallback, "Object");
Task.Run(() =>
{
DoSomething("kulala");
});

线程开启的方式

 三种  new Task Task.Run() Task.Factory  Parallel

     Task task = new Task(new Action(() =>
                {
                    Debug.WriteLine("Task学习");
                    this.DoSomething("Seven");
                }));
                task.Start();//线程开启了

     Task.Run(() =>
                {
                    this.DoSomething("Seven");
                });

      TaskFactory factory = Task.Factory;
                factory.StartNew(() =>
                {
                    this.DoSomething("一意");
                });    

List<Action> acitonList = new List<Action>();
acitonList.Add(() => { });
acitonList.Add(() => { });
acitonList.Add(() => { });
Parallel.Invoke(acitonList.ToArray());//也是可以开启线程,可以一次放入很多个委托去执行;

 Parallel

//1.可以传入多个委托
//2.多个委托中的内容是会开启线程来执行---执行这里的线程有可能是新的线程,也有可能是主线程参与计算的
//3.会阻塞主线程---相当于是主线程等待子线程执行结束

          {
                    List<Action> acitonList = new List<Action>();
                    acitonList.Add(() => { });
                    acitonList.Add(() => { });
                    acitonList.Add(() => { });
                    Parallel.Invoke(acitonList.ToArray());//也是可以开启线程,可以一次放入很多个委托去执行;
                }
          ParallelOptions options = new ParallelOptions();
                    options.MaxDegreeOfParallelism = 3;
                    Parallel.Invoke(options,
                        () =>
                        {
                            Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                            this.DoSomething("this is Action 01");
                        },
                        () =>
                        {
                            Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                            this.DoSomething("this is Action 02");
                        },
                        () =>
                        {
                            Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                            this.DoSomething("this is Action 03");
                        });
能不能不阻塞界面?包一个Task   相当于给一个父线程,父线程不参与计算
                {
                    Task.Run(() =>
                    {
                        Parallel.Invoke(
                      () =>
                      {
                          Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                          this.DoSomething("this is Action 01");
                      },
                      () =>
                      {
                          Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                          this.DoSomething("this is Action 02");
                      },
                      () =>
                      {
                          Debug.WriteLine($"线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                          this.DoSomething("this is Action 03");
                      });
                    });
                }
--Parallel是基于Task一个封装;
开启多个线程--Parallel.For Foreach
控制线程的数量-- - Parallel就是可以控制线程的数量,不至于出现线程泛滥的情况

                {   //方式1
                    ParallelOptions options = new ParallelOptions();
                    options.MaxDegreeOfParallelism = 3;
                    Parallel.For(0, 10, options, index =>
                     {
                         Debug.WriteLine($"index:{ index}  线程ID:  {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
                         this.DoSomething("this is Action 03");
                     });
                }
 {  //方式2
  List<int> intlist = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; //100个 100个任务: 如果我使用Parallel来开启线程计算;线程会有100个线程来执行--线程数量会过多; 最好能够控制线程数量 100个任务; 限定开启5个线程;控制反正一共就只有五个线程参与计算 相当于5个线程去平摊这100个任务---既开启了多个线程来执行任务---提高性能---且没有过多的开启线程(过多的开启线程会过多的损耗计算机的资源); ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = 3; //会有17个任务,限定了3个线程去执行这17个任务 Parallel.ForEach(intlist, options, s => { Debug.WriteLine($"index:{ s} 线程ID: {Thread.CurrentThread.ManagedThreadId.ToString("00")}"); this.DoSomething("this is Action 03"); });
}

  

前台线程  后台线程

 // Thread thread = null;
                //thread.Abort();//线程停止;
                //thread.Start();
                //thread.IsBackground = true;//后台线程:进程结束,线程随之消失
                //thread.IsBackground = false;//前台线程:进程结束,线程把内部需要执行的动作执行完毕,然后消失

父子级线程

一个Task内部,开启了几个线程以后;Task内部的线程可以理解为子线程;
父线程在等待的时候,子线程没有线程等待;子线程可能内容还没有执行完毕,父线程就已经结束了;   ------父线程只管生不管养

Task task = new Task(() =>
                {
                    Debug.WriteLine($"****************task开始了: {Thread.CurrentThread.ManagedThreadId.ToString("00")} ***************");
                    Task task1 = new Task(() =>
                    {
                        Debug.WriteLine($"****************task1: {Thread.CurrentThread.ManagedThreadId.ToString("00")} ***************");
                        Thread.Sleep(1000);
                        Debug.WriteLine("我是task1线程");
                    });
                    Task task2 = new Task(() =>
                    {
                        Debug.WriteLine($"****************task2: {Thread.CurrentThread.ManagedThreadId.ToString("00")} ***************");
                        Thread.Sleep(1000);
                        Debug.WriteLine("我是task2线程");
                    });
                    task1.Start();
                    task2.Start();
                    Debug.WriteLine($"****************task: {Thread.CurrentThread.ManagedThreadId.ToString("00")} ***************");
                });
                task.Start();//线程启动了
                task.Wait();   //单个线程的等待;等待task 内部的内容执行完毕,这里会卡顿界面;是主线程等待;
                // task.Wait();//等待执行完成:
                task.Wait(TimeSpan.FromMilliseconds(1100));
                task.Wait(1000);//限时等待;过时不候

 线程优先级

 TaskCreationOptions.PreferFairness 相对来说比较公平执行的:如果是先申请的线程,就会优先执行;   可以在源数据中查看

线程等待

Thread.Sleep(3000);//主线程执行到这儿会卡顿等待;等待3000ms后继续往后;

Task.Delay(3000).ContinueWith(t =>
{Debug.WriteLine($"****************Delay || 线程ID: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");

3000ms以后, 不卡顿界面  去执行一段业务逻辑:执行的动作就是ContinueWith内部的委托;ContinueWith内部的执行有可能是一个全新的线程去执行,也有可能是主线程去执行

Task几个主要应用

ContinueWhenAny       ContinueWhenAll   WaitAny   WaitAll

List<Task> taskList = new List<Task>();
TaskFactory factory = new TaskFactory();
taskList.Add(factory.StartNew(obj => Coding("")));
taskList.Add(factory.StartNew(obj => Coding("")));

factory.ContinueWhenAny(taskList.ToArray(), ts =>
{
Debug.WriteLine($"{ts.AsyncState}开发完毕准备环境。。。");     //相当于是一个回调;主线程执行的时候,这里是不卡段界面的;当taskList集合中的某一个线程执行结束语了;就触发后面委托中的动作;---不卡顿界面--用户体验就更好
});

factory.ContinueWhenAll(taskList.ToArray(), ts =>
{
Debug.WriteLine($"所有人开发完毕,我们一起庆祝一下,一起吃个饭!");
});

Task.WaitAny(taskList.ToArray());     ///等待几个线程中的某一个线程执行结束;---主线程会等待-- - 会卡顿界面;一直到某一个线程执行结束后,才往后执行;--体验不好

Task.WaitAll(taskList.ToArray());    //主线程会等待-- 一直到所有的线程执行结束,才往后执行;- 会卡顿界面;--体验不好

  

 

posted @ 2021-12-01 18:02  wolfsocket  阅读(140)  评论(0编辑  收藏  举报