Task多线程并行开发

Net 4.0之后出现的多线程对象。

Task 其实时Thread 和ThreadPool的结合和优化

Thread 通过windbg观察执行完后GC下次回收,时间空间开销不小,调用过多时间片切换频繁影响效率

ThreadPool 受限CPU核心线程数,CLR控制回收.

Task使用方法
【1】new一个新的Task来启动(包含很多的重载)
Task task = new Task(() =>
  {
      //在这个地方写我们需要的逻辑...
      Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
  });
  task.Start();

我们看到还是转换成了线程池的.

【2】使用Task的Run()方法
        Task task = Task.Run(() =>
        {
            //在这个地方写我们需要的逻辑...
            Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
        });

这个通过windbg查看也一样的

【3】使用TaskFactory启动(类似于ThreadPool)
        Task task = Task.Factory.StartNew(() =>
        {
            //在这个地方写我们需要的逻辑...
            Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
        });
这个通过windbg查看也一样的

【4】以上是三种异步方式。对于第一种情况,我们也可以使用同步执行(阻塞)
        Task task = new Task(() =>
          {
              Console.WriteLine("子线程开始执行......");
              Thread.Sleep(1000);
              Console.WriteLine("子线程Id={0}", Thread.CurrentThread.ManagedThreadId);
          });
        task.RunSynchronously();//这个是同步方法

现在这个我们在windbg看到时和同步方法一模一样的,用完就没了.


【5】Task还可以有返回值Task<TResult> 它的父类也是Task
        var task = new Task<string>(() =>
          {
              //在这个地方可以编写自己的业务逻辑...
              return "We are Studying Task!";
          });
        task.Start();
        var result = task.Result;//获取结果数据
        Console.WriteLine(result);

 

 

 

Task阻塞方法

 
            //Task阻塞方法
            Task task1 = new Task(()=>
            {
                Thread.Sleep(1000);
                Console.WriteLine("This is subThread1...");
            });
            task1.Start();

            Task task2 = new Task(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("This is subThread2...");
            });
            task2.Start();

            //等待所有任务线程执行完毕再执行
            var taskArray = new Task[2] { task1, task2 };
            //Task.WaitAll(taskArray);

            //只要有一个任务完成就可以执行后面的任务
            Task.WaitAny(taskArray);

            //还有task.wait()类似与join();了解一下即可不常用.


            Console.WriteLine("This is Main Thread...");

【2】同学们注意了,上面的这些操作都没有返回值。
那么我们就考虑到一个延续的问题
           【1】//WhenAll

           Task task1 = new Task(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("This is subThread1...");
            });
            task1.Start();

            Task task2 = new Task(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("This is subThread2...");
            });
            task2.Start();

            Task.WhenAll(task1,task2).ContinueWith(
                (task3)=>
                {
                    Console.WriteLine("This is subThread3..."
                        +Thread.CurrentThread.ManagedThreadId);
                });//线程的延续...(主线下不等待,子线程依次执行)

            Console.WriteLine("This is Main Thread...");



        //【2】线程的延续...(任何一个线程执行完,就执行后面的信任,主线程依然不等待)
        //    Task.WhenAny(task1, task2).ContinueWith(task3 =>
        //    {
        //        Console.WriteLine("Child(3)Time={0}", DateTime.Now.ToLongTimeString());
        //    });
       //【3】使用工厂完成:ContinueWhenAll

以上几个都是根据自己需求来吧.都可以实现依次执行的效果,在有些需求中我们必须这样依次执行才能保证系统的正确性稳定性.
 
 

子线程的附加 TaskCreationOptions creationOptions

 
           #region 子线程的附加 TaskCreationOptions creationOptions

            Task parentTask = new Task(()=>
            {
                Task task1 = new Task(()=>
                {
                    Console.WriteLine("This is attact Thread1....");
                },TaskCreationOptions.AttachedToParent);
                task1.Start();

                Task task2 = new Task(() =>
                {
                    Console.WriteLine("This is attact Thread2....");
                }, TaskCreationOptions.AttachedToParent);
                task2.Start();
            });
            parentTask.Start();
            parentTask.Wait();//等待任务完成 相当于waitall(task1,task2);

            #endregion

            Console.WriteLine("This is Main Thread...");

子线程附加可以用在一个大模块中,这些子线程可以附加到一个父任务中.

TaskCreationOptions枚举中还有其他枚举大家可以仔细看看
 

Task常见枚举 (延续、完成、取消)

 
            //任务1
            Task task1 = new Task(() =>
            {
                Console.WriteLine("Child(1)Time={0}  Id={1}", DateTime.Now.ToLongTimeString(),                      Thread.CurrentThread.ManagedThreadId);
            });

            //任务2
            Task task2 = task1.ContinueWith((task) =>
            {
                Console.WriteLine("Child(2)Time={0}  Id={1}", DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
            });
            //任务3
            Task task3 = task2.ContinueWith((task) =>
            {
                Console.WriteLine("Child(3)Time={0}  Id={1}", DateTime.Now.ToLongTimeString(), Thread.CurrentThread.ManagedThreadId);
            });
           task1.Start();//嵌套执行,只需要Start Task1 等待Task1完成 然后执行了Task1的延续,由于Task的延续又在Task2里面,Task2又可以延续。
            //这里的好处就是我们需要队列执行的的时候如何保证它不冲突,这个用处就大了.
 
 

Task组成结构图

 
posted @ 2021-01-28 14:58  wrjhzou  阅读(267)  评论(0编辑  收藏  举报