首页 > 其他分享 >Task基础-创建Task,Task传参,获取Task返回值

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

时间:2023-12-20 15:47:05浏览次数:34  
标签:传参 Task 创建 sum System task using 返回值

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

  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,创建,sum,System,task,using,返回值
From: https://www.cnblogs.com/Alex80/p/17916623.html

相关文章

  • A Simple Task 题解
    这道题比较简单,简述一下思路。考虑状压\(DP\)。设\(dp_{i,j}\)表示走到第\(i\)个点,之前走过的点的状态为\(j\)的环的数量。这里有一个细节,就是我们都钦定每个走过的第一点是整个状态中编号最小的点,这样不会重复计算。考虑如何进行转移。如果当前点的编号比走过的最小编......
  • ABC311G One More Grid Task 题解
    给出\(n\timesm\)的矩阵\(a\)。求权值最大子矩形的权值。一个矩形的权值定义为它里面全部数的和乘上最小值。\(n,m\leq300,0\leqa_{i,j}\leq300\)。枚举最小的数\(a_{i,j}\)。则在满足\(a_{i,j}\)是最小值时,包含\((i,j)\)的矩形一定是极大的。这些矩形不好枚举,......
  • C# 加深印象之 Task.Run和new Task的区别
    publicasyncTaskTest(){vartask=AAA();Log.Info("调用AAA");awaitTask.Delay(2000);Log.Info("等待2秒任务尚未执行完毕");awaittask;//等待任务完成Log.Info("等待AAA......
  • Vue 图片上传formdata()传参形式
    1.接口需要设置 headers:{'Content-Type':'multipart/form-data'}, from-data流的形式传参 2.jshtml://文件上传<divclass="file"><el-buttontype="primary"style="width:170px"icon="el-icon-upload......
  • el-date-picker 限制时间范围 picker-options 传参
    需求el-date-picker限制时间范围的选取,不能超过某个区间[startDate,endDate]。问题在于,disabledDate函数的参数默认是time,无法传递自定义参数[startDate,endDate]。分析传递给picker-options的值只能是对象。无法传递单个对象,但是可以传递一个返回对象的函数。解......
  • Java 枚举传参获取值
    平常常用的根据传参获取枚举值publicenumSaleTypeStrEnum{JX,//OTHERS;publicstaticSaleTypeStrEnumgetByName(StringsaleTypeStr){for(SaleTypeStrEnumvalue:SaleTypeStrEnum.values()){if(value.name().equals(saleTypeStr)){re......
  • Time slice based task routine in C
          基于时间片的轮询任务调度实例。#include<stdint.h>#include<stdio.h>#include<WinSock2.h>#defineMAX_TASK_NUM10#defineMAX_HALF_WORD0xffff#definefalse0#definetrue1staticuint16_tg_ti......
  • url传参是接送字符串时,报400错误
    URL传递参数,参数是JSON字符串,将字符串拼在url?后,该url不识别,为什么会报400?当URL传递参数,参数是JSON字符串时,如果将字符串直接拼在URL后面,可能会导致URL无法正确识别,从而报400错误。这是因为URL有特定的字符限制和编码要求,而JSON字符串中可能包含URL不安全的字符,如特殊字符、空格、......
  • Tekton TaskRun 基础
    TaskRun概述TaskRun允许您在集群上实例化和执行Task。任务指定执行容器映像的一个或多个Steps,每个容器映像执行特定的构建工作。TaskRun按照指定的顺序执行任务中的Steps,直到所有Steps执行成功或失败。TaskRun配置清单apiVersion:tekton.dev/v1#指定API版本。kind:TaskR......
  • Tekton Tasks 基础
    Tasks概述Task是一系列Step的组合,每个Step主要负责运行特定的构建或交付工具从而完成相关的一次特定事项;Task以Kubernetes集群上Pod运行。Task是名称空间级别的资源。Tasks组成Parameters:是使得Task及Pipeline资源定义出的“模板”更加具有通用性的关键要素之一Steps:具体执行的......