多线程编程总结:三、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完成前开始,这个参数可以避免这种问题。

 

posted @ 2021-05-21 17:31  .NET架构  阅读(673)  评论(0编辑  收藏  举报