ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Task基础-创建Task,Task传参,获取Task返回值

2022-06-21 23:02:20  阅读:96  来源: 互联网

标签:传参 Task Console sum System task using 返回值


  1. Task基础介绍
  2. Task的创建
  3. 获取Task的执行结果
  4.  补充细节

1、Task基础介绍

Task类是Task Programming Library(TPL)中最核心的一个类,下面我将会像大家展示如何使用一些方法来创建不同类型的Task,取消Task,等待Task执行完成,获取Task执行后的结果和对异常进行处理。

我们用静态方法:Task.Factory.StartNew()来创建了一个最简单的Task--在屏幕上打印一句话。这段代码确实简单,而且都没有任何输入和需要返回的结果。

  Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Hello World");
            });

 

2、Task的创建

为了执行一个简单的Task,一般进行以下步骤:

第一步,创建一个Task类的实例

第二步,传入一个Action委托,这个委托中的方法就是这个Task运行时要执行的方法,而这个委托必须作为Task构造函数的一个参数传入。传入委托作为参数的时候有多种方法:传入匿名委托,lambda表达式等。

第三步,调用Task实力的start()方法来运行。

当这个Task实例开始运行的时候,它就被传给了内部的一个task scheduler,这个scheduler负责把我们创建的task交给底下的线程去执行。
    下面就看看代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Task创建
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //第一种,使用委托和方法
            Task task1 = new Task(new Action(printMsg));
            

            //第二种,使用匿名委托
            Task task2 = new Task(delegate { 
                printMsg ();
            });

            //第三种,使用lambda和方法
            Task task3 = new Task(()=>printMsg ());

            //第四种,使用lambda和匿名方法
            Task task4 = new Task(()=> {
                printMsg();
            });

            task1.Start();
            task2.Start();
            task3.Start();
            task4.Start();
            //第四种,使用Task.Run(),Task.Run()的返回值也是一个Task
            Task.Run(()=> {
                printMsg();
            });

 

Console.Read(); } static void printMsg() { Console.WriteLine("hello world"); } } }

上面代码创建Task的方法和我们之前的第一段代码的创建Task的方法不同。在之前我们采用的是Task.Factory.StartNew()方法来创建的,这个方法创建Task并且开始运行Task,其实两端代码的结果是一样的,这里给出一点建议:如果这是想简单的创建一个Task,那么使用Factory.NewStart()来创建,很简便,如果像对所创建的Task附加更多的定制和设置特定的属性,那么还是得一步一步的按照我们说的那些步骤来。

3、获取Task的执行结果

在创建Task的时候,我们在构造函数中传入了一个System.Action的委托,如果我们想要把一些参数传入到Task中,那么我们可以Task的另一个构造函数public Task(Action<object> action, object state),传入System.Action<object>的委托,其中的那个object就是我们传入的参数。举例如下:

using System;
using System.Threading.Tasks;

namespace Task传入参数
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string[] messages = { "First task", "Second task","Third task", "Fourth task" };
            foreach (var item in messages)
            {
                //第一种方法
                Task task = new Task((s) => printMsg((string)s), item);
                //第二种方法
                //Task task = new Task(()=>printMsg(item));
                task.Start();
                
            }
            Console.WriteLine("Main method complete. Press enter to finish.");
            Console.ReadLine();
        }

        static void printMsg(string msg)
        {
            Console.WriteLine($"print message:{msg}");
        }
    }
}

注意:我们在传入参数后,必须把参数转换为它们原来的类型,然后再去调用相应的方法。例子中,因为System.Action对应的方法是printMessage()方法,而这个方法的要求的参数类型是string,所以要转换为string。

两种传入参数的方法有什么区别?目前我还不太清楚,肯是因为第二种方法会导致闭包。

  想向Task传入参素,只能用System.Action<object>

3、获取Task的执行结果

如果要获取Task的结果,那么在创建Task的时候,就要采用Task<T>来实例化一个Task,其中的那个T就是task执行完成之后返回结果的类型。之后采用Task实例的Result属性就可以获取结果,只有在task执行完成之后,才能获取到Result的值。
    代码显示如下:

1、使用Task开启一个线程,计算10以内求和,并获得返回值

using System;
using System.Threading.Tasks;
using System.Threading;

namespace Task获得返回值
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = new Task<int>(() => getSum());
            task.Start();

            Console.WriteLine($"task result is {task.Result}");
            Console.ReadLine();
        }

        static int getSum()
        {
            int sum = 0;
            for (int i = 0; i < 10; i++)
            {
                sum = sum + i;
                Thread.Sleep(100);
            }
            return sum;
        }
    }    
}

 

2、对上面的代码进行修改,计算任意数字内的求和,需要输入一个参数,并获得返回值。

using System;
using System.Threading.Tasks;
using System.Threading;

namespace Task获得返回值
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = new Task<int>((l) => getSum((int)l),10);
            task.Start();

            Console.WriteLine($"task result is {task.Result}");
            Console.ReadLine();
        }

        static int getSum(int len)
        {
            int sum = 0;
            for (int i = 0; i < len; i++)
            {
                sum = sum + i;
                Thread.Sleep(100);
            }
            return sum;
        }
    }    
}

3、通过Task.Factory.StartNew<TResualt>创建一个Task,并获得结果。

using System;
using System.Threading.Tasks;

namespace TaskFactory获得返回值
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Task<int> task = Task.Factory.StartNew<int>((n) => {

                int sum = 0;
                for (int i = 0; i < (int)n; i++)
                {
                    sum = sum + i;
                }
                return sum;
            }, 100);

            Console.WriteLine($"sum = {task.Result}");
            Console.ReadLine();
        }
    }
}

 

4、补充细节

在创建Task的时候,Task有很多的构造函数的重载,一个主要的重载就是传入TaskCreateOptions的枚举:     
    TaskCreateOptions.None:用默认的方式创建一个Task
    TaskCreateOptions.PreferFairness:请求scheduler尽量公平的执行Task(后续文章会将是,Task和线程一样,有优先级的)
    TaskCreateOptions.LongRunning:声明Task将会长时间的运行。
    TaskCreateOptions.AttachToParent:因为Task是可以嵌套的,所以这个枚举就是把一个子task附加到一个父task中。

    最后要提到的一点就是,我们可以在Task的执行体中用Task.CurrentId来返回Task的唯一表示ID(int)。如果在Task执行体外使用这个属性就会得到null。

 

标签:传参,Task,Console,sum,System,task,using,返回值
来源: https://www.cnblogs.com/hanzq/p/16397239.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有