• 多线程编程总结:三、Task的使用和意义


    Task 

           创建每个线程需要占用1MB的虚拟内存,并且线程过多会导致CPU耗费大量时间在切换不同线程上。所以在之前我们会使用线程池来自动分配线程。

           在.Net Framwork 4,TPL提供了一个新的方式去创建线程,那就是Task类,它告诉任务调度器有异步工作需要做,任务调度器有多重测量,但是默认是从线程池请求一个线程给Task类使用。

           Task类是异步执行一个工作任务,而委托(例如:Action)是同步执行一个工作任务。所以Task是将委托(Action)从同步执行模式转变为异步执行。

           Task.Run()是直接热启动,也就是立刻执行,而如果通过Task构造函数实例化的任务就是冷启动,不会立即执行。热启动任务的状态是不确定的。当遇上一组Task正在运行,而我们需要等待所有任务都完成时就会使用Task.WaitAll(),只需要等待任一任务完成就使用Task.WaitAny();

           如果我们想要这个任务返回一个结果,我们需要使用Task<T>类型异步运行一个Func<T>.例如:

                Task<string> task = Task.Run<string>(() => {
                    return string.Empty;
                });

            任务结束之后,IsCompleted属性设置为true,但是该任务实际上运行可能是正常的,也可能是出错结束。需要读取Task.Status属性得到具体状态,其中只要Status为RuntoCompletion / Canceled / Faulted,都会设置IsCompleted=true。

            Task.CurrentId是唯一性标识,在调试的时候非常有用,另外AsyncState可以为任务关联额外数据,将需要开启这个Task的源对象或者某一些Target对象带入Task内部。

    控制流

            控制流实际上就是系统决定接下来要做什么?例如Console.WriteLine(str.GetHashCode());那么这句代码的控制流就是首先计算出str的HashCode值,然后将这个返回值作为WriteLine的参数,在这个过程中就产生了控制点的延续,实际上C#编程是控制流延续直到结束。任何给定代码的延续实际上是分为两种可能,“正常”和“异常”。

            普通的同步操作是自上而下的延续控制流,但是异步任务是在原有的控制流上添加了一个新的分支维度,也就是原有的Task.Start()语句执行后,控制流继续往下执行,同时Task委托的主体代码也开始执行了,在原有控制流的基础上增加了一条分支控制流开始执行。

    Task.ContinueWith()

             使用CountinueWith()方法可以串行的链接运行任务,只有前面一个任务完成之后才可以继续完成第二个任务。同时该方法返回的也是Task对象,还可以继续串接第三个任务,所以是可以链接任意长度的任务链的。

             ContinueWith()有很多重载,其中有一个ContinueWithOptions枚举值可以提供多重串行运行可能性

    枚举值 具体应用
    None 默认为前面任务完成,不管任务状态是什么都运行下一个任务
    PreferFairness 公平调度,不保证谁先运行
    LongRunning 告诉调度器这是一个I/O受限的高延迟任务,调度器可先处理后面的其他工作,少用
    AttachedToParent 指定任务连接到任务层次结构中的父任务
    DenyChildAttach 试图创建子任务将引发异常
    NotOnRanToCompletion 如果延续任务的先驱任务成功完成,则不应该调度延续任务。
    NotOnFaulted 如果延续任务的先驱任务失败,引发了异常,则不应该调度延续任务。
    NotOnCanceled 如果延续任务的先驱任务取消了,则不应该调度延续任务。
    OnlyOnCanceled 如果延续任务的先驱任务取消了,才调度该延续任务。 
    OnlyOnFaulted 如果延续任务的先驱任务失败,引发了异常,才调度延续任务
    OnlyOnRanToCompletion 如果延续任务的先驱任务成功完成,才应该调度延续任务。
    ExecuteSynchronously 直接在先驱任务的线程上继续运行,而无需重新从线程池拿线程。
    HideScheduler 隐藏线程调度器
    LazyCancellation

    延续任务将监视取消的标志的时间推迟到前驱任务结束之后。

    有延续任务t1、t2、t3,其中t2任务在t1完成前取消了,那么t3可能会在t1完成前开始,这个参数可以避免这种问题。

  • 相关阅读:
    HDU 3416 Marriage Match IV(SPFA+最大流)
    asp.net一些很酷很实用的.Net技巧
    asp.net部分控件使用和开发技巧总结
    ASP_NET Global_asax详解
    asp.net 多字段模糊查询代码
    Asp.net中防止用户多次登录的方法
    SQL Server 事务、异常和游标
    有关Cookie
    asp.net 连接sql server 2005 用户 'sa' 登录失败。asp.net开发第一步连接的细节问题
    asp.net生成高质量缩略图通用函数(c#代码),支持多种生成方式
  • 原文地址:https://www.cnblogs.com/chengxingliang/p/14794766.html
Copyright © 2020-2023  润新知