前面介绍了Task的由来,以及简单的使用,包括开启任务,处理任务的超时、异常、取消、以及如果获取任务的返回值,在回去返回值之后,立即唤起新的线程处理返回值、且如果前面的任务发生异常,唤起任务如果有效的处理异常等关于Task的知识。所以本文将介绍Task更多的用法和特性.

一、如果通过一个任务创建多个子任务.

1、Task支持一个任务,创建多个子任务,并且保持关联.

        static void Main(string[] args)
{
var parentTask = new Task<int[]>(() =>
{
//开启多个子任务
var results = new int[]; //创建子任务,并将子任务的值赋给results变量,并通过TaskCreationOptions.AttachedToParent,将其关联到父任务,如果不指定,该任务将独立于父任务单独执行
//这里有个奇怪的问题,只能使用new Task的方式去创建关联到父任务的子任务,因为Task.Run没有提供这个方法,可以通过扩展方法解决这个问题
new Task(() => results[] = ChildThreadOne(), TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[] = ChildThreadTwo(), TaskCreationOptions.AttachedToParent).Start(); return results;
});
parentTask.Start();
parentTask.ContinueWith(x =>
{
Console.WriteLine("当父任务执行完毕时,CLR会唤起一个新线程,将父任务的返回值(子任务的返回值)输出,所以这里不会有任何的线程发生阻塞");
foreach (var re in parentTask.Result)
{
Console.WriteLine("子任务的返回值分别为:{0}", re);
}
});
Console.WriteLine("主线程不会阻塞,它会继续执行");
Console.ReadKey();//必须加这行代码,因为Task时线程池线程,属于后台线程
} /// <summary>
/// 子任务一
/// </summary>
static int ChildThreadOne()
{
Thread.Sleep();//模拟长时间计算操作
Console.WriteLine("子任务一完成了计算任务,并返回值:{0}", );
return ;
} /// <summary>
/// 子任务一
/// </summary>
static int ChildThreadTwo()
{
Thread.Sleep();//模拟长时间计算操作
Console.WriteLine("子任务二完成了计算任务,并返回值:{0}", );
return ;
}

二、关于Task的资源释放问题.

如果你看过Task的源码,你会发现下面这个有趣的问题:

ok,你会想它想释放什么呢?

没错,当Task任务,指定了TaskContinuationOptions枚举状态,且指定的值如下:

那么,直接return,什么资源释放操作都不做.

如果任务没有完成,就调用Dispose方法,那么直接抛异常,如果完成了,它就释放了ManualResetEventSlim信号量(后面的文章会介绍).所以如果你在task中使用了其它的一些非托管资源,那么最好在代码里自己手动释放,在使用完之后。或者自己实现了Task的派生类,把需要用的非托管资源加进去,然后在使用完派生类之后,调用Dispose方法.

三、关于Task的几个常用属性

1、Id属性,每个Task对象都有一个Id属性,全局唯一,且每次创建新的任务,这个值都会递增1.

2、TaskStatus状态

    //
// 摘要:
// 表示 System.Threading.Tasks.Task 的生命周期中的当前阶段。
public enum TaskStatus
{
//
// 摘要:
// 该任务已初始化,但尚未被计划。
Created = ,
//
// 摘要:
// 该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。
WaitingForActivation = ,
//
// 摘要:
// 该任务已被计划执行,但尚未开始执行。
WaitingToRun = ,
//
// 摘要:
// 该任务正在运行,但尚未完成。
Running = ,
//
// 摘要:
// 该任务已完成执行,正在隐式等待附加的子任务完成。
WaitingForChildrenToComplete = ,
//
// 摘要:
// 已成功完成执行的任务。
RanToCompletion = ,
//
// 摘要:
// 该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的
// CancellationToken 发出了信号。 有关详细信息,请参阅任务取消。
Canceled = ,
//
// 摘要:
// 由于未处理异常的原因而完成的任务。
Faulted =
}

构造完Task对象是,状态为Created,当任务启动时,状态变为WaitingToRun,当Task实际在线程上运行时,状态变为Running.如果当前任务为父任务,且它已经执行完毕,等待其它子任务执行完毕的时候,其状态变为WaitingForChildrenToComplete.如果任务完成可能会出现以下几种状态:RanToCompletion(已成功完成执行的任务)、Canceled(取消状态)、

Faulted(任务出错).

这里需要注意一个特殊的状态WaitingForActivation

当使用Task对象的ContinueWith的Task对象处理改状态,意味者该Task任务的调度由任务基础结构控制.也就是该任务的调度只有当前面的任务执行完之后,由CLR发起执行调用.

C# 多线程六之Task(任务)二的更多相关文章

  1. C# 多线程六之Task(任务)三之任务工厂

    1.知识回顾,简要概述 前面两篇关于Task的随笔,C# 多线程五之Task(任务)一 和 C# 多线程六之Task(任务)二,介绍了关于Task的一些基本的用法,以及一些使用的要点,如果都看懂了,本 ...

  2. 异步多线程 Thread ThreadPool Task

    一.线程 Thread ThreadPool 线程是Windows任务调度的最小单位,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以 ...

  3. 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    [源码下载] 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel) 作者:webabcd 介绍重新想象 W ...

  4. C#多线程实现方法——Task/Task.Factary

    原文:C#多线程实现方法--Task/Task.Factary Task 使用 Task以及Task.Factory都是在.Net 4引用的.Task跟Thread很类似,通过下面例子可以看到. st ...

  5. .net 多线程 Thread ThreadPool Task

    先准备一个耗时方法 /// <summary>/// 耗时方法/// </summary>/// <param name="name">< ...

  6. c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习

    c#中@标志的作用   参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...

  7. 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html

    .Net多线程编程—任务Task   1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...

  8. Elasticsearch入门教程(六):Elasticsearch查询(二)

    原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...

  9. Java多线程技术学习笔记(二)

    目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...

随机推荐

  1. 学习fortran77基础语法

    Program ParamaterDefine Implicit None C FORTRAN变量名和关键字不区分大小写.但调用外部函数的话,需要在编译选项里指定 c 大小写等选项 因为链接器是区分大 ...

  2. IntellJ IDEA 2017 激活编译器配置,读取多个配置文件

    1.设置编译器,找到1,点击2 2.输入设置命令:--spring.profiles.active=test,如果是多个文件输入--spring.profiles.active=test,dev 3. ...

  3. Typecho 二次开发文档链接

    快速入门模板入门 模板制作快速入门推荐目录结构 Typecho模板的推荐页面构成模板文件说明 Typecho主题制作文件结构 页面制作制作functions文件: Typecho的functions. ...

  4. linux 定时器 定时执行php

    输入命令:    crontab -e 添加定时命令 每隔一分钟执行一次php //复制一下命令即可.  */1 * * * * /usr/bin/curl -o /home/logs/temp.lo ...

  5. std::string的find问题研究

    https://files-cdn.cnblogs.com/files/aquester/std之string的find问题研究.pdf 目录 目录 1 1. 前言 1 2. find字符串 1 3. ...

  6. 1114 Family Property

    This time, you are supposed to help us collect the data for family-owned property. Given each person ...

  7. 第四章-shceme和数据类型优化

    选择数据类型的原则: 1.更小通常更好.因为占用更少磁盘,内存和cpu缓存.但是要确保没有低估,因为进行alter时,是很耗时和头疼的操作.所以当无法确定数据类型的时候,选择不会超过范围的最小类型. ...

  8. IOS绘图详解

    http://blog.163.com/wkyuyang_001/blog/static/10802122820133190545227/

  9. QT中的线程与事件循环理解(2)

    1. Qt多线程与Qobject的关系 每一个 Qt 应用程序至少有一个事件循环,就是调用了QCoreApplication::exec()的那个事件循环.不过,QThread也可以开启事件循环.只不 ...

  10. ASP.NET Web API 框架研究 Action方法介绍

    在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...