威尼斯人线上娱乐

【威尼斯人线上娱乐】中TASK类的应用,总计范围的异步操作

2 4月 , 2019  

职务概述

线程(Thread)是创办并发的底层工具,因而有早晚的局限性(不易得到重回值(必须通过创设共享域);十分的破获和拍卖也麻烦;同时线程执行完毕后无法再次拉开该线程),这几个局限性会骤降质量同时影响并发性的贯彻(不不难组合较小的产出操作完毕较大的面世操作,会增多手工业同步处理(加锁,发送功率信号)的依赖,不难并发难题)。

线程池的(ThreadPool)QueueUserWorkItem艺术很容发起壹次异步的总计范围操作。但以此技能壹样具有许多限制,最大的标题是从未内建的机制让您驾驭操作在何时做到,也未曾编写制定在操作完结时获得再次回到值。

Task类能够化解上述全体的题材。

任务(Task)意味着3个透过或不经过线程完结的出现操作,任务是可组合的,使用延续(continuation)可将它们串联在壹齐,它们能够使用线程池裁减运维延迟,可使用回调方法幸免四个线程同时等待I/O密集操作。

 

只是,在前几天那篇博客中,大家要领会的是,QueueUserWorkItem那几个技术存在很多限量。个中最大的难题是未曾叁个内建的编写制定让你领悟操作在如什么日期候做到,也绝非二个机制在操作达成是获得1个重临值,这个难点驱动大家都不敢启用那几个技能。

乘胜 .NET
4.0的到来,她与原先各版本的3个醒目差异正是互为功能的拉长,以此来适应那些多核的世界。于是引入了两个新定义—职责,作为支撑互相运算的严重性组成都部队分,同时,也当作对线程池的八个补给和完善。从所周知,使用线程池有多少个明显的短处,那正是壹旦把大家要履行的任务放进去后,何时实施到位,以及实践到位后须要再次回到值,大家都不可能通过嵌入的法子而得知。由于职责(Task)的出产,使得我们对相互编制程序变得简单,而且并非关切底层是怎么落实的,由于比线程池更灵活,假诺能操纵好Task,对于写出飞速的互相代码极度有帮带。

前言

基础义务(Task)

微软在.NET 4.0 引入任务(Task)的定义。通过System.Threading.Tasks命名空间应用任务。它是在ThreadPool的底蕴上进展打包的。Task私下认可都是应用池化线程,它们都是后台线程,那代表主线程截止时别的任务也会跟着告壹段落。

起步二个职务有八种方法,如以下示例:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("主线程Id:{0}", Thread.CurrentThread.ManagedThreadId);
 6             int workerThreadsCount, completionPortThreadsCount;
 7             ThreadPool.GetAvailableThreads(out workerThreadsCount, out completionPortThreadsCount);
 8             Console.WriteLine("剩余工作线程数:{0},剩余IO线程数{1}", workerThreadsCount, completionPortThreadsCount);
 9             //第一种:实例化方式Start启动
10             {
11                 Task task = new Task(() =>
12                 {
13                     Test("one-ok");
14                 });
15                 task.Start();
16             }
17             //第二种:通过Task类静态方法Run方式进行启动
18             {
19                 Task.Run(() =>
20                 {
21                     Test("two-ok");
22                 });
23             }
24             //第三种:通过TaskFactory的StartNew方法启动
25             {
26                 TaskFactory taskFactory = new TaskFactory();
27                 taskFactory.StartNew(() =>
28                 {
29                     Test("three-ok");
30                 });
31             }
32             //第四种:.通过Task.Factory进行启动
33             {
34                 Task taskStarNew = Task.Factory.StartNew(() =>
35                 {
36                     Test("four-ok");
37                 });
38             }
39             //第五种:通过Task对象的RunSynchronously方法启动(同步,由主线程执行,会卡主线程)
40             {
41                 Task taskRunSync = new Task(() =>
42                 {
43                     Console.WriteLine("线程Id:{0},执行方法:five-ok", Thread.CurrentThread.ManagedThreadId);
44                 });
45                 taskRunSync.RunSynchronously();
46             }
47             Thread.Sleep(1000);
48             ThreadPool.GetAvailableThreads(out workerThreadsCount, out completionPortThreadsCount);
49             Console.WriteLine("剩余工作线程数:{0},剩余IO线程数{1}", workerThreadsCount, completionPortThreadsCount);
50             Console.ReadKey();
51         }
52         static void Test(string o)
53         {
54             Thread.Sleep(2000);
55             Console.WriteLine("线程Id:{0},执行方法:{1}", Thread.CurrentThread.ManagedThreadId, o);
56         }
57         /*
58          * 作者:Jonins
59          * 出处:http://www.cnblogs.com/jonins/
60          */
61     }

实施结果:

威尼斯人线上娱乐 1

地点示例中除去使用RunSynchronously方法运行的是共同职务(由启用的线程执行任务)外,别的几种办法之中都由线程池内的劳引力线程处理。

说明

一.事实上Task.Factory类型自身正是TaskFactory(职务工厂),而Task.Run(在.NET肆.5引入,4.0版本调用的是后人)是Task.Factory.StartNew的简写法,是继任者的重载版本,更灵敏简单些。

贰.调用静态Run方法会自动创立Task对象并立刻调用Start

叁.如Task.Run等方式运营义务并从未调用Start,因为它成立的是“热”义务,相反“冷”职分的创立是透过Task构造函数。

 

Microsoft为了克服那个限制(同时缓解任何一些难点),引入了职务(tasks)的定义。顺带说一下我们得经过System.Threading.Tasks命名空间来利用它们。

一、新建义务

学学那件业务是1个司空眼惯,不可能停。。。其余那篇已经看过七个月过去,但觉得有点工作不总计跟没做没啥差距,遂记下此文

返回值(Task<TResult>)&状态(Status)

Task有2个泛型子类Task<TResult>,它同意职务回到叁个值。调用Task.Run,传入二个Func<Tresult>代理或协作的Lambda表明式,然后查询Result属性获得结果。假使职分未有到位,那么访问Result属性会阻塞当前线程,直至职责实现

1     public static Task<TResult> Run<TResult>(Func<TResult> function);

而职责的Status性子可用于跟踪职分的履市价况,如下所示:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task<int> task = Task.Run(() =>
 6             {
 7                 int total = 0;
 8                 for (int i = 0; i <= 100; i++)
 9                 {
10                     total += i;
11                 }
12                 Thread.Sleep(2000);
13                 return total;
14             });
15             Console.WriteLine("任务状态:{0}",task.Status);
16             Thread.Sleep(1000);
17             Console.WriteLine("任务状态:{0}", task.Status);
18             int totalCount = task.Result;//如果任务没有完成,则阻塞
19             Console.WriteLine("任务状态:{0}", task.Status);
20             Console.WriteLine("总数为:{0}",totalCount);
21             Console.ReadKey();
22         }
23     }

施行如下:

 威尼斯人线上娱乐 2

Reulst属性内部会调用Wait(等待);

任务的Status属性是一个TaskStatus枚举类型:

1  public TaskStatus Status { get; }

表达如下:

枚举值 说明
Canceled

任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;

或者在该任务开始执行之前,已向该任务的 CancellationToken 发出了信号。

Created 该任务已初始化,但尚未被计划。
Faulted 由于未处理异常的原因而完成的任务。
RanToCompletion 已完成执行的任务。
Running 任务正在运行,尚未完成。
WaitingForActivation 该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。
WaitingForChildrenToComplete 该任务已完成执行,正在隐式等待附加的子任务完成。
WaitingToRun 该任务已被计划执行,但尚未开始执行。

 

近来本身要说的是,用线程池不是调用ThreadPool的QueueUserWorkItem方法,而是用任务来做相同的事:

      在System.Threading.Tasks命名空间下,有多个新类,Task及其泛型版本Task<TResult>,那八个类是用来成立职责的,要是进行的代码不须要重返值,请使用Task,若须要再次来到值,请使用Task<TResult>。

1.CL奥迪Q伍线程池基础

职务集合重返值(WhenAll&WhenAny)

 Task中有13分有利的对相互运维的职分集合获取再次回到值的不二等秘书诀,比如WhenAllWhenAny

复制代码 一        static void Main(string[] args) 

     
创设职责的点子有三种,一种是透过Task.Factory.StartNew方法来创制多少个新职分,如:

贰.ThreadPool的简易利用演练

1.WhenAll

WhenAll:等待提供的具有 Task 对象完毕实施进程(全部任务总体成就)。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             List<Task<int>> taskList = new List<Task<int>>();//声明一个任务集合
 6             TaskFactory taskFactory = new TaskFactory();
 7             for (int i = 0; i < 5; i++)
 8             {
 9                 int total = i;
10                 Task<int> task = taskFactory.StartNew(() => Test(total));
11                 taskList.Add(task);//将任务放进集合中
12             }
13             Console.WriteLine("主线程Id:{0},继续执行A.....", Thread.CurrentThread.ManagedThreadId);
14             Task<int[]> taskReulstList = Task.WhenAll(taskList);//创建一个任务,该任务将集合中的所有 Task 对象都完成时完成
15             for (int i = 0; i < taskReulstList.Result.Length; i++)//这里调用了Result,所以会阻塞线程,等待集合内所有任务全部完成
16             {
17                 Console.WriteLine("返回值:{0}", taskReulstList.Result[i]);//遍历任务集合内Task返回的值
18             }
19             Console.WriteLine("主线程Id:{0},继续执行B.....", Thread.CurrentThread.ManagedThreadId);
20             Console.ReadKey();
21         }
22         private static int Test(int o)
23         {
24             Console.WriteLine("线程Id:{0},Task执行成功,参数为:{1}", Thread.CurrentThread.ManagedThreadId, o);
25             Thread.Sleep(500 * o);
26             return o;
27         }
28     }

推行结果:

威尼斯人线上娱乐 3

2        { 

      Task task = Task.Facotry.StartNew(()=>Console.WriteLine(“Hello,
World!”));//此行代码执行后,任务就起头施行

3.实践上下文

2.WhenAny

WhenAny:等待提供的任1 Task 对象实现实施进度(只要有一个任务到位)。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             List<Task<int>> taskList = new List<Task<int>>();//声明一个任务集合
 6             TaskFactory taskFactory = new TaskFactory();
 7             for (int i = 0; i < 5; i++)
 8             {
 9                 int total = i;
10                 Task<int> task = taskFactory.StartNew(() => Test(total));
11                 taskList.Add(task);//将任务放进集合中
12             }
13             Console.WriteLine("主线程Id:{0},继续执行A.....", Thread.CurrentThread.ManagedThreadId);
14             Task<Task<int>> taskReulstList = Task.WhenAny(taskList);//创建一个任务,该任务将在集合中的任意 Task 对象完成时完成
15             Console.WriteLine("返回值:{0}", taskReulstList.Result.Result);//得到任务集合内最先完成的任务的返回值
16             Console.WriteLine("主线程Id:{0},继续执行B.....", Thread.CurrentThread.ManagedThreadId);
17             Console.ReadKey();
18         }
19         private static int Test(int o)
20         {
21             Console.WriteLine("线程Id:{0},Task执行成功,参数为:{1}", Thread.CurrentThread.ManagedThreadId, o);
22             Thread.Sleep(500 * o);
23             return o;
24         }
25     }

实施结果(那里再次回到值肯定会是0,因为休眠最短):

威尼斯人线上娱乐 4

 

3            Console.WriteLine(“主线程运行”); 

      另1种形式是由此Task类的构造函数来创建3个新任务,如:

4.合作式撤废和过期,System.Threading.CancellationTokenSource的简练利用

等候(Wait)&执行格局(TaskCreationOptions)

4            //ThreadPool.QueueUserWorkItem(StartCode,5); 

      Task task = new Task(()=>Console.WriteLine(“Hello,
World!”));//此处只把要马到功成的行事交给义务,但职责未有初叶

5.任务

一.任务等待(Wait)

调用职务的Wait主意可以卡住任务直至义务实现,类似于线程的join。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task task = Task.Run(() =>
 6             {
 7                 Console.WriteLine("线程执行Begin");
 8                 Thread.Sleep(2000);
 9                 Console.WriteLine("线程执行End");
10             });
11             Console.WriteLine("任务是否完成:{0}", task.IsCompleted);
12             task.Wait();//阻塞,直至任务完成
13             Console.WriteLine("任务是否完成:{0}", task.IsCompleted);
14             Console.ReadKey();
15         }
16     }

推行如下:

威尼斯人线上娱乐 5

注意

线程调用Wait方法时,系统一检查测线程要等待的Task是不是已经起来履行。若是是线程则会堵塞直到Task运转停止停止。但要是Task还尚无开头施行职分,系统恐怕(取决于TaskScheduler)使用调用Wait的线程来实施Task,那种意况下调用Wait的线程不会卡住,它会履行Task并立时赶回。好处在于没有线程会被卡住,所以收缩了能源占用。倒霉的地点在于参加线程在调用Wait前已经获得了三个线程同步锁,而Task试图获取同一个锁,就会促成死锁的线程。

5            new Task(StartCode, 5).Start();

      task.Start();//调用Start方法后,义务才会在现在有些时候开始执行。

6.职务调度器

二.职务执行形式(TaskCreationOptions)

咱俩明白为了创设贰个Task,须求调用构造函数并传递二个Action或Action<object>委托,即使传递的是可望三个Object的点子,还非得向Task的构造函数穿都要传给操作的实参。还是能够选拔向构造器传递1些TaskCreationOptions标记来决定Task的施行措施。

 TaskCreationOptions为枚举类型

枚举值 说明
None 默认。
PreferFairness 尽可能公平的方式安排任务,即先进先执行。
LongRunning 指定任务将是长时间运行的,会新建线程执行,不会使用池化线程。
AttachedToParent 指定将任务附加到任务层次结构中的某个父级
DenyChildAttach 任务试图和这个父任务连接将抛出一个InvalidOperationException
HideScheduler 强迫子任务使用默认调度而非父级任务调度

在私下认可情状下,Task内部是运作在池化线程上,那种线程会万分适合执行短计算密集作业。假设要执行长阻塞操作,则要防止使用池化线程。

在池化线程上运维二个长职分难点一点都不大,可是只要要同时运营多少个长任务(越发是会阻塞的天职),则会对质量发生潜移默化。最佳利用:TaskCreationOptions.LongRunning。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             int workerThreadsCount, completionPortThreadsCount;
 6             ThreadPool.GetAvailableThreads(out workerThreadsCount, out completionPortThreadsCount);
 7             Console.WriteLine("剩余工作线程数:{0},剩余IO线程数{1},主线程Id:{2}", workerThreadsCount, completionPortThreadsCount, Thread.CurrentThread.ManagedThreadId);
 8             Task task = Task.Factory.StartNew(() =>
 9             {
10                 Console.WriteLine("长任务执行,线程Id:{0}", Thread.CurrentThread.ManagedThreadId);
11                 Thread.Sleep(2000);
12             }, TaskCreationOptions.LongRunning);
13             Thread.Sleep(1000);
14             ThreadPool.GetAvailableThreads(out workerThreadsCount, out completionPortThreadsCount);
15             Console.WriteLine("剩余工作线程数:{0},剩余IO线程数{1},主线程Id:{2}", workerThreadsCount, completionPortThreadsCount, Thread.CurrentThread.ManagedThreadId);
16             Console.ReadKey();
17         }
18     }

推行结果如下:

威尼斯人线上娱乐 6

注意

一旦使运转I/O密集义务,则能够使用TaskCompletionSource和异步函数(asynchronous
functions),通过【威尼斯人线上娱乐】中TASK类的应用,总计范围的异步操作。回调(一连)实现并发性,而是不通过线程完毕。

倘诺使运行总括密集性任务,则能够利用一个劳动者/消费者队列,控制那个任务的面世数量,防止出现线程和进度阻塞的题材。

 

 陆            Console.WriteLine(“主线程运营到此!”); 

     
同时,大家得以调用Wait方法来等待任务的做到或然调用IsCompleted属性来判断职务是不是到位。须要证实的是,二种创制职务的方法都能够匹配TaskCreationOptions枚举来落到实处大家对职分执行的作为具体控制,
同时,那三种创设格局允许大家传递多个TaskCreationOptions对象来撤消正在运营中的职务,请看职责的裁撤。

一、CLLX570线程池基础

继承(continuation)&再三再四选项(TaskContinuationOptions)

延续(continuation)会告诉任务在成功后继续执行上边包车型地铁操作。一连平时由二个回调方法达成,它会在操作落成以往执行二次。给多少个职分叠加三番五次的秘诀有二种

7            Thread.Sleep(1000); 

2、职责的撤消

如二6章所述,创设和销毁线程是四个值钱的操作,要消耗大量的时日。其它太多的线程会浪费内部存款和储蓄器能源。由于操作系统必须调度可运营的线程并推行上下文切换,所以太多的线程还对品质不利。

1.GetAwaiter

任务的措施GetAwaiter是Framework
4.伍新扩张的,而C#
5.0的异步作用使用了那种措施,因而它不行重要。给三个任务叠加延续如下:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task<int> task = Task.Run(() =>
 6              {
 7                  int total = 0;
 8                  for (int i = 0; i <= 100; i++)
 9                  {
10                      total += i;
11                  }
12                  Thread.Sleep(2000);
13                  return total;
14              });
15             var awaiter = task.GetAwaiter();
16             awaiter.OnCompleted(() =>
17             {
18                 int result = awaiter.GetResult();//在延续中获取Task的执行结果
19                 Console.WriteLine(result);
20             });
21             Console.ReadKey();
22         }
23     }

施行结果决定台会打字与印刷:5050。

调用GetAwaiter会回来一个等待者(awaiter)对象,它会让辅导(antecedent)职责在职分成功(或出错)之后执行1个代理。已经成功的任务也能够附加多个后续,那事三番5回会登时执行。

注意

1.等待者(awaiter)能够是轻易对象,但无法不带有特定的多少个章程和2个Boolean类型属性。

1   public struct TaskAwaiter<TResult> : ICriticalNotifyCompletion, INotifyCompletion
2     {
3         public bool IsCompleted { get; }
4         public TResult GetResult();
5         public void OnCompleted(Action continuation);
6     }

2.指引任务出现谬误,那么当一而再代码调用awaiter.GetResult()时就会重新抛出尤其。大家能够要求调用GetResult,而是直接待上访问开始任务的Result属性(task.Result)。

GetResult的功利是,当向导任务出现谬误时,卓殊能够一贯抛出而不封装在AggregateException中。

3.固然出现一块上下文,那么会自动捕捉它,然后继续提交到那些上下文中。在无需1并上下文的景况下1般不利用那种办法,使用ConfigureAwait代表它。它常常会使延续运行在辅导任务所在的线程上,从而幸免不要求的过载。

1    var awaiter = task.ConfigureAwait(false).GetAwaiter();

8        } 

     那世界唯1不变的正是浮动,当外部规范产生变化时,大家兴许会收回正在执行的任务。对于.NET
肆.0在此之前,.NET未有提供多个松手的化解方案来撤废线程池中正在实践的代码,但在.NET
四.0中,大家有了Cooperative
Cancellation模式,那使得撤销正在实施的天职变得相当不难。如下所示:

为了千锤百炼这些景况,CLHaval包蕴了代码管理它和谐的线程池(thread
pool),线程池是您的应用程序能运用的线程的集结。

2.ContinueWith

另一种附加再而三的艺术是调用任务的ContinueWith方法:

 1         static void Main(string[] args)
 2         {
 3             Task<int> task = Task.Run(() =>
 4             {
 5                 int total = 0;
 6                 for (int i = 0; i <= 100; i++)
 7                 {
 8                     total += i;
 9                 }
10                 Thread.Sleep(2000);
11                 return total;
12             });
13             task.ContinueWith(continuationAction =>
14             {
15                 int result = continuationAction.Result;
16                 Console.WriteLine(result);
17             });
18             Console.ReadKey();
19         }

ContinueWith自己会回来三个Task,它不行适用于添加越多的一连。然后一旦职责出现谬误,大家必须一贯处理AggregateException。

假若想让持续运营在集合个线程上,必须钦命 TaskContinuationOptions.ExecuteSynchronously;不然它会弹回线程池。ContinueWith专门适用于并行编制程序场景。

9 10        private static void StartCode(object i)

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

namespace TaskDemo 

    class Program 
    { 
        static void Main() 
        { 
            CancellationTokenSource cts = new
CancellationTokenSource(); 
            Task t = new Task(() => LongRunTask(cts.Token)); 
            t.Start(); 
            Thread.Sleep(2000); 
            cts.Cancel(); 
            Console.Read(); 
        }

        static void LongRunTask(CancellationToken token) 
        {

             //此处方法模拟多少个耗费时间的工作 
            for (int i = 0; i < 1000; i++) 
            { 
                if (!token.IsCancellationRequested) 
                { 
                    Thread.Sleep(500); 
                    Console.Write(“.”); 
                } 
                else 
                { 
                    Console.WriteLine(“职责撤消”); 
                    break; 
                } 
            } 
        } 
威尼斯人线上娱乐,    } 
}

每CL索罗德2个线程池,那一个线程池由CLENCORE控制的具有AppDomain共享。

叁.再三再四选项(TaskContinuationOptions)

在使用ContinueWith时得以钦点职务的持续选项即TaskContinuationOptions,它的前八个枚举类型与事先说的TaskCreationOptions枚举提供的注解完全相同,补充后续几个枚举值:

枚举值 说明
LazyCancellation 除非先导任务完成,否则禁止延续任务完成(取消)。
NotOnRanToCompletion 指定不应在延续任务前面的任务已完成运行的情况下安排延续任务。
NotOnFaulted 指定不应在延续任务前面的任务引发了未处理异常的情况下安排延续任务。
NotOnCanceled 指定不应在延续任务前面的任务已取消的情况下安排延续任务。 
OnlyOnCanceled 指定只应在延续前面的任务已取消的情况下安排延续任务。
OnlyOnFaulted 指定只有在延续任务前面的任务引发了未处理异常的情况下才应安排延续任务。
OnlyOnRanToCompletion 指定只有在延续任务前面的任务引发了未处理异常的情况下才应安排延续任务。
ExecuteSynchronously 指定希望由先导任务的线程执行,先导任务完成后线程继续执行延续任务。

 

ExecuteSynchronously是指同步施行,多个任务都在同2个=线程壹前一后的举办。

ContinueWith结合Task孔蒂nuationOptions使用的演示:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Task<int> task = Task.Run(() =>
 6             {
 7                 int total = 0;
 8                 for (int i = 0; i <= 100; i++)
 9                 {
10                     total += i;
11                 }
12                 if (total == 5050)
13                 {
14                     throw new Exception("错误");//这段代码可以注释或开启,用于测试
15                 }
16                 return total;
17             });
18             //指定先导任务无报错的延续任务
19             task.ContinueWith(continuationAction =>
20             {
21                 int result = continuationAction.Result;
22                 Console.WriteLine(result);
23             }, TaskContinuationOptions.NotOnFaulted);
24             //指定先导任务报错时的延续任务
25             task.ContinueWith(continuationAction =>
26             {
27                 foreach (Exception ex in continuationAction.Exception.InnerExceptions)//有关AggregateException异常处理后续讨论
28                 {
29                     Console.WriteLine(ex.Message);
30                 }
31             }, TaskContinuationOptions.OnlyOnFaulted);
32             Console.ReadKey();
33         }
34     }

实施结果会打字与印刷:报错,如若注释掉抛出十一分的代码则会打字与印刷5050。

 

11        {

 

CL陆风X八初阶化时,线程池中是未曾线程的。在里面,线程池维护了1个操作请求队列。应用程序执行2个异步操作时,就调用有个别方法,将二个记下项(entry)追加到线程池的体系中,线程池的代码从那个队列中领取记录项,将那几个记录项派发(dispatch)给一个线程池线程。假设线程池中尚有线程,就创设2个新线程。

TaskCompletionSource

另1种创立职分的格局是应用TaskCompletionSource。它同意创制一个职分,并得以职责分发给使用者,并且那个使用者能够应用该职责的别样成员。它的兑现原理是透过二个足以手动操作的“附属”职务,用于提示操作完毕或出错的大运。

TaskCompletionSource的的确成效是创办一个不绑定线程的天职(手动控制任务工作流,能够使您把制造任务和姣好职务分别)

那种形式非凡适合I/O密集作业:可以动用全体任务的优点(它们能够生成再次回到值、万分和后续),但不会在操作实施期间阻塞线程。

比如说,假使二个职分急需等待二秒,然后回到十,大家的方法会重返在四个贰秒后实现的职务,通过给职责叠加1个后续就足以在不打断任何线程的前提下打字与印刷那么些结果,如下:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var awaiter = Demo(2000).GetAwaiter();//得到任务通过延续输出返回值
 6             awaiter.OnCompleted(() =>
 7             {
 8                 Console.WriteLine(awaiter.GetResult());
 9             });
10             Console.WriteLine("主线程继续执行....");
11             Console.ReadKey();
12         }
13         static Task<int> Demo(int millis)
14         {
15             //创建一个任务完成源
16             TaskCompletionSource<int> taskCompletionSource = new TaskCompletionSource<int>();
17             var timer = new System.Timers.Timer(millis) { AutoReset = false };
18             timer.Elapsed += delegate
19             {
20                 timer.Dispose(); taskCompletionSource.SetResult(10);//写入返回值
21             };
22             timer.Start();
23             return taskCompletionSource.Task;//返回任务
24         }
25     }

实施结果:

威尼斯人线上娱乐 7

注意:倘诺反复调用SetResult、SetException或SetCanceled,它们会抛出特别,而TryXXX会重返false。

 

1二            Console.WriteLine(“先导实施子线程…{0}”,i);

三、职务的格外机制

借使应用程序向线程池发出许多请求,线程池会尝试只用二个线程来服务具有请求。可是,假如你的应用程序发出请求的进程抢先了线程池线程处理它们的速度,就会创制额外的线程。

职分撤除(CancellationTokenSource)

一些情状下,后台职责或许运行十分短日子,撤消任务就老大实惠了。.NET提供了一种标准的职务撤消机制可用于基于职务的异步方式

取消基于CancellationTokenSource类,该类可用来发送撤除请求。请求发送给引用CancellationToken类的任务,当中CancellationToken类与CancellationTokenSource类相关联。

行使示例如下:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //构造函数 指定延迟2秒后自动取消任务
 6             CancellationTokenSource source = new CancellationTokenSource(2000);
 7             //注册一个任务取消后执行的委托
 8             source.Token.Register(() =>
 9             {
10                 Console.WriteLine("线程Id:{0} 任务被取消后的业务逻辑正在运行", Thread.CurrentThread.ManagedThreadId);
11             });
12             //启动任务,将取消标记源带入参数
13             Task.Run(() =>
14             {
15                 while (!source.IsCancellationRequested)//IsCancellationRequested为True时取消任务
16                 {
17                     Thread.Sleep(100);
18                     Console.WriteLine("线程Id:{0} 任务正在运行", Thread.CurrentThread.ManagedThreadId);
19                 }
20             }, source.Token);
21             //主线程挂起2秒后手动取消任务
22             {
23                 //Thread.Sleep(2000);
24                 //source.Cancel();//手动取消任务
25             }
26             //主线程不阻塞,2秒后自动取消任务
27             {
28                 source.CancelAfter(2000);
29             }
30             Console.ReadKey();
31         }
32     }

实践结果:

威尼斯人线上娱乐 8

根据Register办法绑定职务打消后的嘱托

1   public CancellationTokenRegistration Register(Action callback);
2   public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext);
3   public CancellationTokenRegistration Register(Action<object> callback, object state);
4   public CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext);

手动撤除义务Cancel方法

活动撤废任务

1.CancelAfter方法后边能够教导参数钦赐延迟多少后时间收回职责。

1   public void CancelAfter(TimeSpan delay);
2   public void CancelAfter(int millisecondsDelay);

2.CancellationTokenSource构造函数能够辅导参数钦命延迟多少时间后撤回任务。

1   public CancellationTokenSource(TimeSpan delay);
2   public CancellationTokenSource(int millisecondsDelay);

职务绑定CancellationTokenSource对象,在Task源码中能够教导CancellationToken对象的开发银行职分措施都足以绑定CancellationTokenSource。

威尼斯人线上娱乐 9

 

1三            Thread.Sleep(一千);//模拟代码操作   

   
在职分履行进度中发出的未处理很是,职务会把它权且隐没起来,装进三个集结中。当大家调用Wait方法大概Result属性时,职务会抛出1个AggregateException相当。大家得以经过调用AggregateException对象的只读属性InnerExceptions来获得二个ReadOnlyCollection<Exception>对象,它才是储存抛出12分的聚合,它的第一个成分就是初期抛出的不胜。同样的,AggregateException对象的InnerException属性也会回去最初抛出的百般。

当叁个线程池线程闲着悠闲1段时间之后,线程会自个儿醒来终止本身以自由能源。

异步等待 (Task.Delay)

 异步等待格外实用,因而它成为Task类的三个静态方法

 常用的选用方法有2种,如下:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //第1种
 6             {
 7                 Task.Delay(2000).ContinueWith((o) =>
 8                 {
 9                     Console.WriteLine("线程Id:{0},异步等待2秒后执行的逻辑", Thread.CurrentThread.ManagedThreadId);
10                 });
11             }
12             //第2种
13             {
14                 Task.Delay(3000).GetAwaiter().OnCompleted(() =>
15                 {
16                     Console.WriteLine("线程Id:{0},异步等待3秒后执行的逻辑", Thread.CurrentThread.ManagedThreadId);
17                 });
18             }
19             Console.WriteLine("主线程Id:{0},继续执行", Thread.CurrentThread.ManagedThreadId);
20             Console.ReadKey();
21         }
22     }

推行结果如下:

威尼斯人线上娱乐 10

Task.DelayThread.Sleep的异步版本。而它们的区分如下(引自 禅道 ):

一.Thread.Sleep 是联合延迟,Task.Delay异步延迟。

二.Thread.Sleep 会阻塞线程,Task.Delay不会。

三.Thread.Sleep无法撤消,Task.Delay能够。

四. Task.Delay() 比 Thread.Sleep()
消耗越多的能源,可是Task.Delay()可用于为格局重返Task类型;或然依据CancellationToken撤销标记动态撤销等待。

伍. Task.Delay() 实质创立2个运营给定时间的职务, Thread.Sleep()
使当前线程休眠给定时间。

 

 14        }

   
值得尊敬的是,由于任务的藏匿机制的特征,一旦发生卓殊后,假设大家不调用相应的点子依然性质查看卓殊,大家也无力回天看清是或不是有卓殊发生(Task不会积极抛出非常)。当Task对象被GC回收时,Finalize方法会查检是还是不是有未处理的可怜,借使不幸刚才好有,则Finalize方法会将此AggregateException再一次抛出,倘诺再不幸,大家未有捕获处理那些可怜,则大家的次第会及时暂停运转。假诺发生如此的业务,会是何其大的劫数啊!

贰、ThreadPool的简约利用练习

异常(AggregateException)

与线程区别,职责能够每四日抛出十三分。所以,即便任务中的代码抛出3个未处理极度,那么那么些充足会活动传送到调用Wait()或Task<TResult>的Result属性的代码上。
职分的相当将会自动捕获并抛给调用者。为力保报告富有的不胜,CL哈弗会将那一个封装在AggregateException容器中,该容器公开的InnerExceptions特性中包涵全体捕获的不行,从而更合乎并行编制程序。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             try
 6             {
 7                 Task.Run(() =>
 8                 {
 9                     throw new Exception("错误");
10                 }).Wait();
11             }
12             catch (AggregateException axe)
13             {
14                 foreach (var item in axe.InnerExceptions)
15                 {
16                     Console.WriteLine(item.Message);
17                 }
18             }
19             Console.ReadKey();
20         }
21     }

上述示范控制台会突显:错误

注意

使用TaskIsFaultedIsCanceled性情,就足以不另行抛出十一分而检查评定出错的天职。
壹.IsFaulted和IsCanceled都回去False,表示一直不错误产生。
二.IsCanceled为True,则职分抛出了OperationCanceledOperation(撤消线程正在执行的操作时在线程中抛出的可怜)。
三.IsFaulted为True,则职务抛出另1种11分,而Exception属性包括了该错误。

15    }

   
为了防止那种不幸的发出,大家能够通过注册TaskScheduler类的静态UnobservedTaskException事件来拍卖那种未被处理的足够,幸免程序的倒台。

威尼斯人线上娱乐 11威尼斯人线上娱乐 12

1.Flatten

当子任务抛出分外时,通过调用Flatten方法,可以解决任意层次的嵌套以简化很是处理。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var parent = Task.Factory.StartNew(() =>
 6             {
 7                 int[] numbers = { 0 };
 8                 var childFactory = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.None);
 9                 childFactory.StartNew(() => 10 / numbers[0]);//除零
10                 childFactory.StartNew(() => numbers[1]);//超出索引范围
11                 childFactory.StartNew(() => throw null);//空引用
12             });
13             try
14             {
15                 parent.Wait();
16             }
17             catch (AggregateException axe)
18             {
19                 foreach (var item in axe.Flatten().InnerExceptions)
20                 {
21                     Console.WriteLine(item.Message);
22                 }
23             }
24             Console.ReadKey();
25         }
26     }

威尼斯人线上娱乐 13

咦,你会意识结果是一样的。再来看看那一个是怎么样:TaskCreationOptions这些类型是三个枚举类型,传递壹些标明来控制Task的履行形式。TaskCreationOptions定义如下:慢点,注释很详细,看看那个有裨益,TaskScheduler(职务调度器)不懂没提到,请继续往下看,作者会介绍的,但请留心,那一个标识都只是局地提出而已,在调度八个Task时,或许会、也大概不会选用这几个建议,可是有一条要注意:AttachedToParent标志,它总会取得Task选拔,因为它和TaskScheduler自个儿毫无干系。

肆、职务运维任务

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine($"Main Thread,当前线程:{Thread.CurrentThread.ManagedThreadId}");
            ThreadPool.QueueUserWorkItem(Calculate,5);
            Console.WriteLine($"Main Thread doing other work,当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(1000);
            Console.WriteLine("hi <Enter> to end this program~~");
            Console.Read();
        }

        //这个方法的签名必须匹配waitcallback委托
        public static void Calculate(object state)
        {
            //这个方法由一个线程池线程执行
            Console.WriteLine($"In Calculate:state={state},当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(1000);
            //这个方法返回后,线程回到池中,等待另一个任务
        }
    }

2.Handle

 假使要求只捕获特定项目相当,一视同仁抛此外门类的这多少个,Handle措施为此提供了一种快捷格局。

Handle接受三个predicate(相当断言),并在每一种内部非凡上运行此断言。

1 public void Handle(Func<Exception, bool> predicate);

借使断言重临True,它认为该越发是“已处理”,当全部尤其过滤之后:

一.假设拥有越发是已处理的,至极不会抛出。

贰.比方存在卓殊未处理,就会协会1个新的AggregateException对象来含有那一个非凡并抛出。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             var parent = Task.Factory.StartNew(() =>
 6             {
 7                 int[] numbers = { 0 };
 8                 var childFactory = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.None);
 9                 childFactory.StartNew(() => 10 / numbers[0]);//除零
10                 childFactory.StartNew(() => numbers[1]);//超出索引范围
11                 childFactory.StartNew(() => throw null);//空引用
12             });
13             try
14             {
15                 try
16                 {
17                     parent.Wait();
18                 }
19                 catch (AggregateException axe)
20                 {
21                     axe.Flatten().Handle(ex =>
22                     {
23                         if (ex is DivideByZeroException)
24                         {
25                             Console.WriteLine("除零-错误处理完毕");
26                             return true;
27                         }
28                         if (ex is IndexOutOfRangeException)
29                         {
30                             Console.WriteLine("超出索引范围-错误处理完毕");
31                             return true;
32                         }
33                         return false;//所有其它 异常重新抛出
34                     });
35 
36                 }
37             }
38             catch (AggregateException axe)
39             {
40                 foreach (var item in axe.InnerExceptions)//捕获重新抛出的异常
41                 {
42                     Console.WriteLine(item.Message);
43                 }
44             }
45             Console.ReadKey();
46         }
47     }

推行结果:

威尼斯人线上娱乐 14

 

来看下那段代码:

    职责的有力与灵活之①是,当大家完结三个职责时,可以活动起先3个新职务的推行。如下所示:

View Code

 结语

一.async和await那多个重大字下篇记录。

二.职分调度器(TaskScheduler)是Task之所以如此灵活的本来面目,大家常说Task是在ThreadPool上更升级化的包装,其实一点都不小程度上归功于那些目的,思索下篇要不要说一下,但实则小编看的都胸口痛…

3.Task类包蕴众多的重载,最棒F1二跳到Task内精晓下结构。

 

1        static void Main(string[] args) 

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

namespace TaskDemo 

    public class AutoTask 
    { 
        static void Main() 
        { 
            Task task = new Task(() => { Thread.Sleep(5000);
Console.WriteLine(“Hello,”); Thread.Sleep(5000); }); 
            task.Start(); 
            Task newTask = task.ContinueWith(t =>
Console.WriteLine(“World!”)); 
            Console.Read(); 
        } 
    } 
}

对于ContinueWith方法,大家得以包容TaskContinuationOptions枚举,得到更加多大家想要的一坐一起。

 

运转结果:

参考文献 

CLR via C#(第4版) Jeffrey Richter

C#高档编制程序(第8版) C# 6 & .NET Core 1.0   Christian Nagel  

果壳中的C# C#5.0上流指南  何塞普h Albahari

C#并发编制程序 经典实例  斯蒂芬 Cleary

 

2        { 

五、子任务

威尼斯人线上娱乐 15

3            

    职分是协理父子关系的,即在三个职务中创设新职责。如下所示:

突发性上图标注那两行输出结果顺序会本末倒置,那是因为四个方法互相之间是异步运营的,windows调度器决定先调度哪一个线程。

  4            //一千000000那些数字会抛出System.AggregateException 

using System; 
using System.Threading.Tasks;

namespace TaskDemo 

    class ChildTask 
    { 
        static void Main() 
        { 
            Task parant = new Task(() => 
            { 
                new Task(() =>
Console.WriteLine(“Hello”)).Start(); 
                new Task(() => Console.WriteLine(“,”)).Start(); 
                new Task(() =>
Console.WriteLine(“World”)).Start(); 
                new Task(() => Console.WriteLine(“!”)).Start(); 
            }); 
            parant.Start(); 
            Console.ReadLine(); 
        } 
    } 
}

值得注意的是,以上代码中所示的子职务的调用并不是以代码的面世程序为各样来调用的。

三、执行上下文

5  

6、职分工厂

各样线程都涉嫌1个执行上下文数据结构。

6            Taskt = new Task(n => Sum((Int32)n), 1000000000); 

   在有些情形下,大家会遇见创立大气的职务,而恰好那一个职分共用某些状态参数(如CancellationToken),为了幸免大量的调用职责的构造器和一次又二回的参数字传送递,大家得以选取任务工厂来为大家处理这种多量创办工作。如下代码所示:

实施上下文(execution
context)包蕴的东西有安全设置(压缩栈、Thread的Principal属性和Windows的身价)、宿主设置(System.Threading.HostExecutionContextManager)以及逻辑调用上下文数据(参见System.Runtime.Remoting.Messaging.CallContext的LogicalSetData和LogicalGetData方法)。

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

暗许境况下,CL普拉多自动造成开始线程的实践上下文“流向”任何援救线程。那致使将上下文新闻传给帮助线程,但那会对质量造成一定影响。

 捌            //能够今日开头,也得以今后起头  

namespace TaskDemo 

    public class FactoryOfTask 
    { 
        static void Main() 
        { 
            Task parent = new Task(() => 
            { 
                CancellationTokenSource cts = new
CancellationTokenSource(); 
                TaskFactory tf = new TaskFactory(cts.Token); 
                var childTask = new[] 
                { 
                 tf.StartNew(()=>ConcreteTask(cts.Token)), 
                 tf.StartNew(()=>ConcreteTask(cts.Token)), 
                 tf.StartNew(()=>ConcreteTask(cts.Token)) 
                };

那是因为执行上下文中包蕴大批量音信,而采访全部那么些消息,再把它们复制到支持线程,要成本比比皆是日子。

9 10            t.Start();

               
Thread.Sleep(6000);//此处睡眠等职分初阶一定时间后才撤消职分 
                cts.Cancel(); 
            } 
            );

System.Threading.ExecutionContext类,允许你说了算线程的施行上下文怎么样从叁个线程“流向”另叁个。可用那个类
阻止上下文流动以升高应用程序的习性。

1一 12            //Wait显式的守候四个线程达成

            parent.Start();//开头实施职责 
            Console.Read(); 
        }

威尼斯人线上娱乐 16威尼斯人线上娱乐 17

13 14            t.Wait();

        static void ConcreteTask(CancellationToken token) 
        { 
            while (true) 
            { 
                if (!token.IsCancellationRequested) 
                { 
                    Thread.Sleep(500); 
                    Console.Write(“.”); 
                } 
                else 
                { 
                    Console.WriteLine(“义务裁撤”); 
                    break; 
                } 
            } 
        } 
    } 
}

    class Program
    {
        static void Main(string[] args)
        {
            //将一些数据放到Main线程的逻辑调用上下文中
            CallContext.LogicalSetData("Name", "Michael");
            //初始化要由线程池线程做的一些工作
            //线程池线程能访问逻辑调用上下文结构
            ThreadPool.QueueUserWorkItem(
                state => Console.WriteLine($"Name={CallContext.LogicalGetData("Name")}"));
            //阻止Main线程的执行上下文的流动
            ExecutionContext.SuppressFlow();
            //初始化要由线程池做的工作
            //线程池线程不能访问逻辑调用上下文数据
            ThreadPool.QueueUserWorkItem(
                state => Console.WriteLine($"Name={CallContext.LogicalGetData("Name")}"));
            //恢复Main线程的执行上下文的流动,
            //以免将来使用更多的线程池线程
            ExecutionContext.RestoreFlow();

            Console.ReadLine();
        }
    }

15            16            Console.WriteLine(“The Sum is:”+t.Result);

7、职分调度程序

View Code

17        }

    职务的调度通过调度程序来落实的,近年来,.NET
四.0内置三种职责调度程序:线程池职务调度程序(thread pool task
scheduler)和协同上下文职务调度程序(synchronization context task
scheduler)。默许情状下,应用程序使用线程池职分调度程序调用线程池的工作线程来完毕职务,如受总括范围的异步操作。同步上下文职分调度程序日常采用UI线程来形成与Windows
Forms,Windows Presentation
Foundation(WPF)以及SilverLight应用程序相关的职分。

编写翻译后运营结果如下:

18 19        private static Int32 Sum(Int32 i)

   可喜的是,.NET 4.0
提供了TaskScheduler抽象类供开发职员继承来贯彻自定义职分调度程序的开支,有趣味的校友能够尝试。

威尼斯人线上娱乐 18

20        {

八、总结

4、合营式裁撤和过期,System.Threading.CancellationTokenSource的简约利用

21            Int32 sum = 0;

     
职责给了笔者们更加多的方便性、灵活性的同时,也推动了比线程池愈来愈多的财富消耗。若是想收缩财富消耗,请间接使用线程池QueueUserWorkItem方法效果会更好;假设想要越来越多的操纵与世故,任务(Task)是不2的抉择。这些要我们开发者自身去斟酌了。

Microsoft.NET
Framework提供了行业内部的吊销操作方式。这几个情势是合作式的,意味着要撤废的操作必须显式帮忙撤消。

22            for (; i > 0; i–)

     

CancellationToken实例是轻量级值类型,包蕴单个私有字段,即对其CancellationTokenSource对象的引用。

23                checked { sum += i; }

参考文献:《CL逍客 Via C#》,Third edtion, 作者:Jeffrey Richer,726页-739页

在总计范围操作的大循环中,可定时调用CancellationToken的IsCancellationRequsted属性,通晓循环是不是相应提前终止,从而终止计算范围的操作。

24            return sum;

《Introducing .NET 4.0 With Visual Studio 2010》,作者:Alex
Mackey,106页-111页

提前终止的好处在于,CPU不要求再把日子浪费在你对结果不感兴趣的操作上。

25        }

 

威尼斯人线上娱乐 19威尼斯人线上娱乐 20

26    }

    static void Main(string[] args)
        {
            Go();
        }

        public static void Go()
        {
            CancellationTokenSource token = new CancellationTokenSource();
            //将CancellationTokenSource和参数 传入操作
            ThreadPool.QueueUserWorkItem(
                o => Count(token,1000));
            Console.WriteLine($"Hit <Enter> to cancel operation");
            Console.ReadLine();
            token.Cancel();//如果Count方法已返回,Cancel没有任何效果
            //执行cancel后 立即返回,方法从这里继续运行
            Console.ReadLine();
        }
        public static void Count(CancellationTokenSource token,Int32 counto)
        {
            for (int count = 0; count < counto; count++)
            {
                if(token.IsCancellationRequested)
                {
                    Console.WriteLine("操作被取消");
                    break;
                }
                Console.WriteLine(count);
                Thread.Sleep(200); //出于显示目的而浪费一些时间你
            }
            Console.WriteLine("Count is done");
        }

 这段代码大家应该猜得出是什么样意思呢,人人都会写。  但是,小编的结果为何是t.Result而不直接是回去的Sum呢? 
有没有家常便饭的痛感?上面作者的话说那段代码笔者想表明的情趣:  在三个线程调用Wait方法时,系统会检讨线程要等待的Task是还是不是业已初始履行,假若职务正在执行,那么那么些Wait方法会使线程阻塞,知道Task运营停止截止。  就说地方的程序执行,因为拉长数字太大,它抛出算术运算溢出错误,在二个划算范围任务抛出3个未处理的13分时,那几个足够会被“包涵”不并蕴藏到三个相会中,而线程池线程是允许再次回到到线程池中的,在调用Wait方法也许Result属性时,那么些成员会抛出2个System.AggregateException对象。  未来你会问,为何要调用Wait只怕Result?也许直接不查询Task的Exception属性?你的代码就永远注意不到这几个那么些的发出,就算不可能捕捉到那几个可怜,垃圾回收时,抛出AggregateException,进度就会马上终止,那就是“牵一发动全身”,岂有此理程序就融洽关闭了,什么人也不掌握这是何等景况。所以,必须调用前边提到的某部成员,确定保障代码注意到那么些,并从1二分中恢复生机。悄悄告诉您,其实在用Result的时候,内部会调用Wait。  怎么回复?  为了扶持您检查评定未有留意到的分外,能够向TaskScheduler的静态UnobservedTaskException时间阶段二个回调方法,当Task被垃圾回收时,借使出现一个未曾被注意到的分外,CLLacrosse终结器会掀起那一个事件。一旦引发,就会向您的年华处理器方法传递多个UnobservedTaskException伊夫nArgs对象,个中含有了你未曾注意的AggregateException。然后再调用UnobservedTasException伊芙nArgs的SetObserved方法来提出你的老大已经处理好了,从而阻碍CL途胜终止进程。那是个图省事的做法,要少做那一个,宁愿终止进度,也不要呆着已经损坏的气象而再三再四运转。做人也一如既往,病了宁肯休息,也无须带病坚定不移上班,你没那么高大,集团也不须要你的那点伟大,命是协调的。(─.─|||扯远了。  除了单个等待义务,Task
还提供了多个静态方法:WaitAny和WaitAll,他们同意线程等待三个Task对象数组。  WaitAny方法会阻塞调用线程,知道数组中的任何二个Task对象实现,那么些方法会重临三个索引值,指明完毕的是哪叁个Task对象。即便发生超时,方法将回到-1。它能够由此1个CancellationToken撤销,会抛出3个OperationCanceledException。  WaitAll方法也会阻塞调用线程,知道数组中的全部Task对象都形成,假若整个成功就再次来到true,假如超时就回来false。当然它也能收回,同样会抛出OperationCanceledException。  说了那样三个撤销任务的章程,以后来试试那一个法子,加深下影像,修改先前例子代码,完整代码如下:

View Code

 1        static void Main(string[] args) 

运转结果如下图所示:

2        { 

威尼斯人线上娱乐 21

3            CancellationTokenSource cts = new
CancellationTokenSource();

可调用CancellationTokenSource的Register方法登记2个或五个在撤消二个CancellationTokenSource时调用的点子。

 4            

向被撤消的CancellationTokenSource登记1个回调方法,将由调用Register的线程调用回调方法(要是为useSynchronizationContext参数字传送递了true值,就大概要透过调用线程的SynchronizationContext进行)。

  5              

往往调用Register,多个调用方法都会调用。那一个回调方法也许抛出未处理的尤其。

6  7            Taskt = new Task(() => Sum(cts.Token,10000),
cts.Token); 

若果调用CancellationTokenSource的Cancel方法,向它传递true,那么抛出了未处理卓殊的率先个回调方法会阻止别的回调方法的进行,抛出的老大也会从Cancel中抛出。

八  玖            //可现在天上马,也能够现在开头 

比方调用Cancel并向它传递false,那么登记的保有回调方法都会调用。全部未处理的不胜都会添加到3个晤面中。全体回调方法都执行好后,当中任何二个抛出了未处理的老大,Cancel就会抛出1个AggregateException,该特别实例的InnerExceptions属性被设为已抛出的富有尤其对象的汇聚。

10            11            t.Start();

威尼斯人线上娱乐 22威尼斯人线上娱乐 23

12 壹三            //在之后的某部时刻,撤除CancellationTokenSource
以收回Task

        static void Main(string[] args)
        {
            var cts1 = new CancellationTokenSource();
            cts1.Token.Register(() => Console.WriteLine($"cts1被取消"));
            var cts2 = new CancellationTokenSource();
            cts2.Token.Register(() => Console.WriteLine($"cts2被取消"));
            var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
            linkedCts.Token.Register(() => Console.WriteLine($"linkedCts 被取消"));
            cts2.Cancel();
            Console.WriteLine($"cts1 canceled={cts1.IsCancellationRequested},cts2 canceled={cts2.IsCancellationRequested}," +
                $"linkedCts={linkedCts.IsCancellationRequested}");
            Console.ReadLine();
    }    

1四 壹5           
cts.Cancel();//那是个异步请求,Task只怕已经形成了。我是双核机器,Task未有完结过

View Code

1陆 一七 1捌            //注释那个为了测试抛出的可怜

运作结果如下图:

19            //Console.WriteLine(“This sum is:” + t.Result);

威尼斯人线上娱乐 24

20            try

设若要在过一段时间后废除操作,要么用接收延时参数的结构器构造1个CancellationTokenSource对象,要么调用CancellationTokenSource的CancelAfter方法。

21            {

五、任务 

2二                //假如任务现已撤回了,Result会抛出AggregateException

通过观看,大家发现 ThreadPool最大的题材是从没有过内建的体制让你知道
操作在什么样时候做到,以及操作实现时获得再次来到值。鉴于此,Microsoft引入了职责的概念。

23 24                Console.WriteLine(“This sum is:” + t.Result);

上面显示二个运用task的简短例子:

25            }

威尼斯人线上娱乐 25威尼斯人线上娱乐 26

26            catch (AggregateException x)

        static void Main(string[] args)
        {
            Console.WriteLine($"当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            //创建一个Task,现在还没有开始运行
            Task<Int32> t = new Task<int>(n => Sum((Int32)n), 10000);
            //可以后等待任务
            t.Start();
            //可选择显示等待任务完成
            t.Wait();
            //可获得结果(result属性内部会调用Wait)
            Console.WriteLine($"the Sum is:{t.Result},当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadLine();
        }    
         private static Int32 Sum(Int32 n)
        {
            Int32 sum = 0;
            for (; n>0; n--)checked
            {
                sum += n; //如果n太大,会抛出System.OverflowException
            }
            Console.WriteLine($"In Sum,当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            return sum;
        }

27            {

View Code

2八                //将任何OperationCanceledException对象都说是已处理。

运作结果如右图:威尼斯人线上娱乐 27

2玖                //其余任何非凡都导致抛出三个AggregateException,在那之中

壹经总括范围职分抛出未处理的特别,分外会被“吞噬”并蕴藏到多个汇集中,调用wait方法或Result属性时,那么些成员会抛出3个System.AggregateException对象。

30                //只包括未处理的老大

AggregateException提供了一个Handle方法,它为AggregateException中含有的各种至极都调用二个回调方法。回调方法能够为每种相当决定哪些对其拍卖;回调重临true表示万分已处理;再次回到false表示未处理。调用Handle后,借使至少有三个老大未有拍卖,就创办3个新的AggregateException对象,当中只含有未处理的不胜。

31 32                x.Handle(e => e is OperationCanceledException);

Task的静态WaitAny方法会阻塞调用线程,直到数组中的任何Task对象完毕。方法再次来到Int3贰数组索引值,指明达成的是哪个Task的对象

33                Console.WriteLine(“Sum was Canceled”);

Task的静态WaitAll方法也会阻塞调用线程,直到数组中的全部Task对象落成。

34            }

下边演示下task撤消操作和task的不胜处理

35          36        }

威尼斯人线上娱乐 28威尼斯人线上娱乐 29

37 38        private static Int32 Sum(CancellationToken ct ,Int32 i)

         static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            Task<Int32> t = Task.Run(() => Sum(cts.Token, 10000), cts.Token);

            cts.Cancel(); 
            try
            {
                Console.WriteLine($"the Sum is:{t.Result},当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            }
            catch (AggregateException ex)
            {
                //将任何OperationCanceledException对象都是为已处理
                //其他任何异常都造成抛出一个新的AggregateException
                //其中只包含未处理异常
                ex.Handle(e => e is OperationCanceledException);
                Console.WriteLine("Sum was canceled");
            }
            Console.ReadLine();
        }        
         private static Int32 Sum(CancellationToken ct, Int32 n)
        {
            Int32 sum = 0;
            for (; n>0; n--)checked
            {
                //再取消标志引用的CancellationTokenSource上调用Cancel,
                //下面这行代码就会抛出OperationCanceledException
                ct.ThrowIfCancellationRequested();
                sum += n; //如果n太大,会抛出System.OverflowException
            }
            Console.WriteLine($"In Sum,当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            return sum;
        }

39        {

View Code

40            Int32 sum = 0;

调用Wait,恐怕在职务未遂时查询义务的Result属性,极有希望造成线程池创造新线程,那增大了财富的开支,也不便于质量和伸缩性。

41            for (; i > 0; i–)

要明了1个任务在怎么样时候甘休,职责到位时可运营另二个任务。

42            {

Microsoft为大家提供了ContinueWith,上边简单体现使用

肆三                //在撤除标志引用的CancellationTokenSource上一旦调用

威尼斯人线上娱乐 30威尼斯人线上娱乐 31

4四                //Cancel,下边那一行就会抛出OperationCanceledException

        static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            Task<Int32> t = Task.Run(() => Sum(cts.Token, 10000), cts.Token);
            Task cwt= t.ContinueWith(task => Console.WriteLine($"Sum result is {task.Result}"));
        }        
         private static Int32 Sum(CancellationToken ct, Int32 n)
        {
            Int32 sum = 0;
            for (; n>0; n--)checked
            {
                //再取消标志引用的CancellationTokenSource上调用Cancel,
                //下面这行代码就会抛出OperationCanceledException
                ct.ThrowIfCancellationRequested();
                sum += n; //如果n太大,会抛出System.OverflowException
            }
            Console.WriteLine($"In Sum,当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            return sum;
        }

45 46                ct.ThrowIfCancellationRequested();

View Code

47 48                checked { sum += i; }

Task对象内部含有了ContinueWith职责的三个成团。可在调用ContinueWith时传递对1组TaskContinuationOptions枚举值进行判断满足哪些意况才实施ContinueWith。

49            }

威尼斯人线上娱乐 32

50            51            return sum;

偷个懒,哈哈。。。

52        }

职务能够运行多少个子职务,下边不难显示下采取

53    }

威尼斯人线上娱乐 33威尼斯人线上娱乐 34

  那一个事例体现了二个任务在拓展的时候中途撤消的操作,笔者认为它很有趣,你尝试也会发现。  Lamada表明式写这一个,是个亮点,得上学,将CancellationToken闭包变量“传递”。

        static void Main(string[] args)
        {
            Task<Int32[]> task = new Task<Int32[]>(() =>
            {
                var results = new Int32[3];
                new Task(() => results[0] = Sum(1000), TaskCreationOptions.AttachedToParent).Start();
                new Task(() => results[1] = Sum(1000), TaskCreationOptions.AttachedToParent).Start();
                new Task(() => results[2] = Sum(1000), TaskCreationOptions.AttachedToParent).Start();
                return results;
            });
            var cwt = task.ContinueWith(
                parentTask => Array.ForEach(parentTask.Result, Console.WriteLine));
            task.Start();
            Console.ReadLine();    
        }
        private static Int32 Sum( Int32 n)
        {
            Int32 sum = 0;
            for (; n>0; n--)checked
            {
                sum += n; //如果n太大,会抛出System.OverflowException
            }
            Console.WriteLine($"In Sum,当前线程ID:{Thread.CurrentThread.ManagedThreadId}");
            return sum;
        }    

 假如不用Lamada表明式,那难题还真不佳消除:  Taskt = new Task(()
=> Sum(cts.Token,一千0), cts.Token);  Sum(cts.Token,壹仟0)
内的Token须求和cts.Token关联起来,你还能想出怎么关联起来么?

View Code

  好,职分废除也讲玩了,来看个更好用的技艺:

TaskCreationOptions.AttachedToParrent标志将3个Task和创办它的Task关联,结果是唯有全体子任务(以及子职务的子任务)停止运营,不然创立职务(父任务)不认为曾经终结。

1        static void Main(string[] args) 

在三个Task对象的留存里面,可查询Task的只读Status属性领悟它在其生存期的什么岗位。

2        { 

 

3  4            Taskt = new Task(i => Sum((Int32)i),10000); 

要创造一组共享相同配置的Task对象。可创立一个任务工厂来封装通用的铺排。即TaskFactory。

伍  6            //能够今日上马,也得以现在开始  

在调用TaskFactory或TaskFactory<TResult>的静态ContinueWhenAll和ContinueWhenAny方法,无论前置任务是咋办到的,ContinueWhenAll和ContinueWhenAny都会进行后续职务。

7              8            t.Start(); 

6、职务调度器

9 10            Task cwt = 
t.ContinueWith(task=>Console.WriteLine(“The sum
is:{0}”,task.Result));

对于不打听任务调度的小白来讲,恐怕蒙受过上面这些现象

11            cwt.Wait();

威尼斯人线上娱乐 35

12            13        }

哟,怎么会那样吗?为何无法在线程里更新UI组件。

14 15        private static Int32 Sum(Int32 i)

TaskScheduler对象承担履行被调度的天职,同时向Visual
Studio调节和测试器公开职务音讯。

16        {

FCL提供了多个派生自TaskScheduler的项目:线程池职务调度器(thread pool
task scheduler),和共同上下文职责调度器(synchronization context task
scheduler)。

17            Int32 sum = 0;

私下认可意况下,全部应用程序使用的都以线程池职责调度器。可查询TaskScheduler的静态Default属性来赢得对暗中同意职责调度器的引用。

18            for (; i > 0; i–)

二头上下文任务调度器适合提供了图形用户界面的应用程序。它将装有任务都调度给应用程序的GUI线程,使拥有职分代码都能不负众望的更新UI组件。该调度不使用线程池。可实施TaskScheduler的静态FromCurrentSynchronizationContext方法来博取对伙同上下文职务调度器的引用。

19            {

下边突显1个简便的例证,演示怎么样使用同步上下文职务调度器

20                checked { sum += i; }

威尼斯人线上娱乐 36威尼斯人线上娱乐 37

21            }

     public partial class MainForm : Form
    {
        private readonly TaskScheduler m_syncContextTaskScheduler;
        public MainForm()
        {
            //获得一个对同步上下文任务调度器的引用
            m_syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            Text = "Synchronization Context Task Scheduler Demo";
            Visible = true; Width = 400; Height = 400;
        }

        private CancellationTokenSource m_cts;

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if(m_cts!=null)
            {
                m_cts.Cancel(); //一个操作正在运行,取消它
                m_cts = null;
            }
            else
            {
                //任务没有开始启动它
                Text = "Operation running"; 
                m_cts = new CancellationTokenSource();
                //这个任务使用默认任务调度器,在一个线程池线程上运行
                Task<Int32> t = Task.Run(()=>Sum(1000),m_cts.Token);
                //这些任务使用 同步上下文任务调度器,在GUI线程上执行
                t.ContinueWith(task => Text = "Result:" + t.Result,
                    CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion,
                    m_syncContextTaskScheduler);
                t.ContinueWith(task => Text = "Operation canceled ",
                    CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled,
                    m_syncContextTaskScheduler);
                t.ContinueWith(task => Text = "Operation defaulted ",
                    CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
                    m_syncContextTaskScheduler);
            }


            base.OnMouseClick(e);
        }
        private static Int32 Sum(Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--) checked
                {
                    sum += n; //如果n太大,会抛出System.OverflowException
                }
            return sum;
        }
    }

22            23            return sum;

View Code

24        }

单击窗体的客户区域,就会在线程池线程上运维二个划算范围操作。使用线程池线程,因为GUI线程在此期间不会被堵塞,能响应其余UI操作。

25    }

 

ContinueWith? 
啥东西~~??  要写可伸缩的软件,一定无法使您的线程阻塞。那象征如若调用Wait也许在职务未到位时查询Result属性,极有非常大希望造成线程池成立2个新线程,那增大了能源的花费,并损害了紧缩性。  ContinueWith就是3个更好的方法,贰个职责成功时它能够运维另2个职务。上边的事例不会阻塞任何线程。

Parallel就留在下篇来介绍吧。。。

 当Sum的职分到位时,这几个任务会运维另三个任务以展现结果。ContinueWith会再次来到对新的Task对象的1个引用,所以为了见到结果,笔者急需调用一下Wait方法,当然你也能够查询下Result,可能三番五次ContinueWith,重返的那些目的足以忽略,它唯有是三个变量。  还要提出的是,Task对象内部含有了ContinueWith职责的三个汇集。所以,实际上能够用八个Task对象来多次调用ContinueWith。职责到位时,全体ContinueWith职分都会进来线程池队列中,在组织ContinueWith的时候大家能够看来三个TaskContinuationOptions枚举值,不可能忽视,看看它的概念:PrefereFairness是尽量公平的情致,便是较早调度的任务恐怕较早的运维,先来后到,将线程放到全局队列,便足以达成那一个职能。ExecuteSynchronously指同步执行,强制五个任务用同3个线程一前一后运转,然后就一块儿运营了。
看得是或不是晕乎乎
?有这样多枚举例子,怎么控制啊?多看三遍,知道任务的选用景况,以往用起来百步穿杨~想学新技巧,就要能耐住,才能基础巩固。来看个例证,用用那些枚举。

天道酬勤,大道至简,坚定不移。

 1        static void Main(string[] args) 

2        { 

3            Taskt = new Task(i => Sum((Int32)i),10000); 

4  5            t.Start(); 

6  7            t.ContinueWith(task=>Console.WriteLine(“The sum
is:{0}”,task.Result), 8               
TaskContinuationOptions.OnlyOnRanToCompletion); 

9            10           
t.ContinueWith(task=>Console.WriteLine(“Sum
throw:”+task.Exception),11               
TaskContinuationOptions.OnlyOnFaulted);

12            13           
t.ContinueWith(task=>Console.WriteLine(“Sum was
cancel:”+task.IsCanceled),14               
TaskContinuationOptions.OnlyOnCanceled);

15            try

16            {

17                t.Wait();  // 测试用

18            }

19            catch (AggregateException)

20            {

21                Console.WriteLine(“出错”);

22            }

23            24            25        }

26 27        private static Int32 Sum(Int32 i)

28        {

29            Int32 sum = 0;

30            for (; i > 0; i–)

31            {

32                checked { sum += i; }

33            }

34            35            return sum;

36        }

37    }

  ContinueWith讲完了。但是还尚未终止哦。  AttachedToParnt枚举类型(父职责)也无法放过!看看怎么用,写法有点怪异,看看: 

 1        static void Main(string[] args) 

2        { 

3            Taskparent = new Task(() => {

 4                var results = new Int32[3]; 

5                //

 6                new Task(() => results[0] = Sum(10000),
TaskCreationOptions.AttachedToParent).Start(); 

7                new Task(() => results[1] = Sum(20000),
TaskCreationOptions.AttachedToParent).Start(); 

8                new Task(() => results[2] = Sum(30000),
TaskCreationOptions.AttachedToParent).Start(); 

9                return results;

10            });

11 12            var cwt = parent.ContinueWith(
parentTask=>Array.ForEach(parentTask.Result,Console.WriteLine));

13                    14 15            parent.Start();

16            cwt.Wait();

17        }

18 19        private static Int32 Sum(Int32 i)

20        {

21            Int32 sum = 0;

22            for (; i > 0; i–)

23            {

24                checked { sum += i; }

25            }

26            return sum;

27        }

28   
}复制代码Oh,小编都写晕了。。。(+﹏+)~例子中,父职分创造兵运行一个Task对象。暗许情况下,2个职务成立的Task对象是一等职责,这几个职分跟创立它们的可怜职分未有涉及。TaskCreationOptions.AttachedToParent标志将1个Task和创建它的十一分Task关联起来,除非全数子职责(子职分的子职务)停止运转,不然创立职务(父职责)不会觉得已经达成。调用ContinueWith方法创制1个Task时,可以钦赐TaskContinuationOptions.AttachedToParent标志将继续职务置顶为2个子任务。

 看了如此多职务的办法操作示例了,今后来挖挖职务之中结构:  各样Task对象都有1组结合任务情况的字段。  2个Int3二ID(只读属性)代表Task执市场价格况的二个Int3二对父职分的三个引用对Task成立时置顶TaskSchedule的多少个引用对回调方法的1个引用对要传给回调方法的靶子的三个引用(通过Task只读AsyncState属性查询)对叁个ExceptionContext的引用对一个马努alReset伊芙ntSlim对象的引用还有没个Task对象都有对基于供给创制的局地互补状态的1个引用,补充状态包涵那一个:一个CancellationToken一个ContinueWithTask对象集合为抛出未处理非凡的子职责,所准备的三个Task对象集合说了如此多,只想要大家清楚:

固然任务提供了大气效益,但并不是绝非代价的。因为必须为拥有的那么些情状分配内部存储器。倘若不必要职责提供的附加效率,使用ThreadPool.QueueUserWorkItem,财富的利用频率会更高一些。Task类还落到实处了IDispose接口,允许你在用完Task对象后调用Dispose,可是多数不管,让垃圾回收器回收就好。成立3个Task对象时,代表Task唯1的1个Int3二字段初步化为零,TaskID从一上马,每分配3个ID都递增一。顺带说一下,在你调节和测试中查阅2个Task对象的时候,会招致调节和测试器展现Task的ID,从而造成为Task分配八个ID。  这几个ID的意义在于,每种Task都得以用1个唯一的值来标识。Visual
Studio会在它的“并行任务”和交互堆栈“窗口中展现那些职务ID。要清楚的是,那是Visual
Studio自身分配的ID,不是在投机代码中分配的ID,大致不大概将Visual
Studio分配的ID和代码正在做的事情联系起来。要查看本人正值运转的天职,能够在调节的时候查看Task的静态CurrentId属性,假诺未有任务在执行,CurrentId再次回到null。  再看看TaskStatus的值,这一个可以查询Task对象的生存期:这一个在职务局维的时候皆以足以壹一查到的,还有~判断要像那样:一if(task.Status==TaskStatus.RantoCompletion)…为了简化编码,Task只提供多少个只读Boolean属性:IsCanceled,IsFaulted,IsCompleted,它们能回去最后状态true/false。如若Task是由此调用有些函数来创立的,那几个Task对象就会由于WaitingForActivation状态,它会自行运转。最终大家要来领悟一下TaskFactory(任务工厂):

一.索要成立1组Task对象来共享相同的景况

贰.为了幸免机械的将1律的参数字传送给每三个Task的构造器。满意那几个规范就能够创设一个任务工厂来封装通用的地方。TaskFactory类型和TaskFactory类型,它们都派生System.Object。你会学到不壹样的编码格局:复制代码
一        static void Main(string[] args) 2        { 

3            Task parent = new Task(() => 

4            { 

5                var cts = new CancellationTokenSource(); 

6                var tf = new TaskFactory(cts.Token,
TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

7

八                //创造并运维三个子职责

9                var childTasks = new[] {

10            tf.StartNew(() => Sum(cts.Token, 10000)),

11            tf.StartNew(() => Sum(cts.Token, 20000)),

1二            tf.StartNew(() => Sum(cts.Token, Int3贰.马克斯Value))  //
这一个会抛极度

13          };

14

一5                // 任何子任务抛出特别就撤除别的子任务

16                for (Int32 task = 0; task < childTasks.Length;
task++)

17                    childTasks[task].ContinueWith(t =>
cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

18

19                //
全体子职分到位后,从未出错/未打消的职分获得再次回到的最大值

20                // 然后将最大值传给另叁个职分来展现最大结果

21                tf.ContinueWhenAll(childTasks,

22                    completedTasks => completedTasks.Where(t =>
!t.IsFaulted && !t.IsCanceled).Max(t => t.Result),

23                    CancellationToken.None)

24                    .ContinueWith(t => Console.WriteLine(“The
maxinum is: ” + t.Result),

2五                     
TaskContinuationOptions.ExecuteSynchronously).Wait(); // Wait用于测试

26            });

27

28            // 子职分成功后,也显得别的未处理的要命

29            parent.ContinueWith(p =>

30            {

3一                // 用StringBuilder输出全体

32

33                StringBuilder sb = new StringBuilder(“The following
exception(s) occurred:” + Environment.NewLine);

34                foreach (var e in
p.Exception.Flatten().InnerExceptions)

35                    sb.AppendLine(”  ” + e.GetType().ToString());

36                Console.WriteLine(sb.ToString());

37            }, TaskContinuationOptions.OnlyOnFaulted);

38

3九            // 运转父职责

40            parent.Start();

41

42            try

43            {

44                parent.Wait(); //呈现结果

45            }

46            catch (AggregateException)

47            {

48            }

49        }

50

51        private static Int32 Sum(CancellationToken ct, Int32 n)

52        {

53            Int32 sum = 0;

54            for (; n > 0; n–)

55            {

56                ct.ThrowIfCancellationRequested();

57                checked { sum += n; }

58            }

59            return sum;

60        }

61    }

复制代码

职务工厂就这么用,正是3个任务的聚合。

明天看看TaskScheduler(任务调度)

任务基础结构是很灵敏的,TaskScheduler对象功不可没。

TaskScheduler对象承担执行调度的天职,同时向Visual
Studio调节和测试器公开职务信息,就好像1座大桥,让我们能够掌握控制自身的职务线程。

TaskScheduler有多少个派生类:thread pool task
scheduler(线程池任务调度),和synchronization context task
scheduler(同步上下文职务调度器)。暗中同意景况下,所以应用程序使用的都以线程池任务调度器,那些任务调度器将任务调度给线程池的工小编线程。能够查询TaskScheduler的静态Default属性来收获对私下认可职务调度器的二个引用。

共同上下文职分调度器平时用于桌面应用程序,Winfrom,WPF及Silverlight。这些职分调度器将多有职务都调度给应用程序的GUI线程,使全部任务代码都能不负众望更新UI组建,比如按钮、菜单项等。同步上下文职务调度器根本不使用线程池。同样,能够查询TaskScheduler的静态FromCurrentSynchronizationContext方法来赢得对3个齐声上下文职务调度器的引用。

就像是那样创设项目:

一 //同步上下文职分调度

2 TaskScheduler m_syncContextTaskScheduler =

3            TaskScheduler.FromCurrentSynchronizationContext();

任务调度有很多的,下边罗列部分,供参考,更加多的请参考 
它归纳了大气的示范代码。


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图