Task构造
- //原文:http://www.tuicool.com/articles/IveiQbQ
- 创建并且初始化Task
- 使用lambda表达式创建Task
- Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!"));
- var task = new Task(() => Console.Write("Hello"));
- task.Start();
- 用默认参数的委托创建Task
- using System;
- using System.Threading.Tasks;
- namespace MultiThread
- {
- class ThreadTest
- {
- static void Main()
- {
- var task = Task.Factory.StartNew(state => Greet("Hello"), "Greeting");
- Console.WriteLine(task.AsyncState); // Greeting
- task.Wait();
- }
- static void Greet(string message) { Console.Write(message); }
- }
- }
- 这种方式的一个优点是,task.AsyncState作为一个内置的属性,可以在不同线程中获取参数的状态。
- System.Threading.Tasks.TaskCreateOptions
- 创建Task的时候,我们可以指定创建Task的一些相关选项。在.Net .0中,有如下选项:
- LongRunning
- 用来表示这个Task是长期运行的,这个参数更适合block线程。LongRunning线程一般回收的周期会比较长,因此CLR可能不会把它放到线程池中进行管理。
- PreferFairness
- 表示让Task尽量以公平的方式运行,避免出现某些线程运行过快或者过慢的情况。
- AttachedToParent
- 表示创建的Task是当前线程所在Task的子任务。这一个用途也很常见。
- 下面的代码是创建子任务的示例:
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MultiThread
- {
- class ThreadTest
- {
- public static void Main(string[] args)
- {
- Task parent = Task.Factory.StartNew(() =>
- {
- Console.WriteLine("I am a parent");
- Task.Factory.StartNew(() => // Detached task
- {
- Console.WriteLine("I am detached");
- });
- Task.Factory.StartNew(() => // Child task
- {
- Console.WriteLine("I am a child");
- }, TaskCreationOptions.AttachedToParent);
- });
- parent.Wait();
- Console.ReadLine();
- }
- }
- }
- 如果你等待你一个任务结束,你必须同时等待任务里面的子任务结束。这一点很重要,尤其是你在使用Continue的时候。(后面会介绍)
- 等待Task
- 在ThreadPool内置的方法中无法实现的等待,在Task中可以很简单的实现了:
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MultiThread
- {
- class ThreadTest
- {
- static void Main()
- {
- var t1 = Task.Run(() => Go(null));
- var t2 = Task.Run(() => Go());
- Task.WaitAll(t1, t2);//等待所有Task结束
- //Task.WaitAny(t1, t2);//等待任意Task结束
- }
- static void Go(object data) // data will be null with the first call.
- {
- Thread.Sleep();
- Console.WriteLine("Hello from the thread pool! " + data);
- }
- }
- }
- 注意:
- 当你调用一个Wait方法时,当前的线程会被阻塞,直到Task返回。但是如果Task还没有被执行,这个时候系统可能会用当前的线程来执行调用Task,而不是新建一个,这样就不需要重新创建一个线程,并且阻塞当前线程。这种做法节省了创建新线程的开销,也避免了一些线程的切换。但是也有缺点,当前线程如果和被调用的Task同时想要获得一个lock,就会导致死锁。
- Task异常处理
- 当等待一个Task完成的时候(调用Wait或者或者访问Result属性的时候),Task任务中没有处理的异常会被封装成AggregateException重新抛出,InnerExceptions属性封装了各个Task没有处理的异常。
- using System;
- using System.Threading.Tasks;
- namespace MultiThreadTest
- {
- class Program
- {
- static void Main(string[] args)
- {
- int x = ;
- Task<int> calc = Task.Factory.StartNew(() => / x);
- try
- {
- Console.WriteLine(calc.Result);
- }
- catch (AggregateException aex)
- {
- Console.Write(aex.InnerException.Message); // Attempted to divide by 0
- }
- }
- }
- }
- 对于有父子关系的Task,子任务未处理的异常会逐层传递到父Task,并且最后包装在AggregateException中。
- using System;
- using System.Threading.Tasks;
- namespace MultiThreadTest
- {
- class Program
- {
- static void Main(string[] args)
- {
- TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
- var parent = Task.Factory.StartNew(() =>
- {
- Task.Factory.StartNew(() => // Child
- {
- Task.Factory.StartNew(() => { throw null; }, atp); // Grandchild
- }, atp);
- });
- // The following call throws a NullReferenceException (wrapped
- // in nested AggregateExceptions):
- parent.Wait();
- }
- }
- }
- 取消Task
- 如果想要支持取消任务,那么在创建Task的时候,需要传入一个CancellationTokenSouce
- 示例代码:
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MultiThreadTest
- {
- class Program
- {
- static void Main(string[] args)
- {
- var cancelSource = new CancellationTokenSource();
- CancellationToken token = cancelSource.Token;
- Task task = Task.Factory.StartNew(() =>
- {
- // Do some stuff...
- token.ThrowIfCancellationRequested(); // Check for cancellation request
- // Do some stuff...
- }, token);
- cancelSource.Cancel();
- try
- {
- task.Wait();
- }
- catch (AggregateException ex)
- {
- if (ex.InnerException is OperationCanceledException)
- Console.Write("Task canceled!");
- }
- Console.ReadLine();
- }
- }
- }
- 任务的连续执行
- Continuations
- 任务调度也是常见的需求,Task支持一个任务结束之后执行另一个任务。
- Task task1 = Task.Factory.StartNew(() => Console.Write("antecedant.."));
- Task task2 = task1.ContinueWith(task =>Console.Write("..continuation"));
- Continuations 和Task<TResult>
- Task也有带返回值的重载,示例代码如下:
- Task.Factory.StartNew<int>(() => )
- .ContinueWith(ant => ant.Result * )
- .ContinueWith(ant => Math.Sqrt(ant.Result))
- .ContinueWith(ant => Console.WriteLine(ant.Result)); // output 4
- 子任务
- 前面提到了,当你等待一个任务的时候,同时需要等待它的子任务完成。
- 下面代码演示了带子任务的Task:
- using System;
- using System.Threading.Tasks;
- using System.Threading;
- namespace MultiThreadTest
- {
- class Program
- {
- public static void Main(string[] args)
- {
- Task<int[]> parentTask = Task.Factory.StartNew(() =>
- {
- int[] results = new int[];
- Task t1 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
- Task t2 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
- Task t3 = new Task(() => { Thread.Sleep(); results[] = ; }, TaskCreationOptions.AttachedToParent);
- t1.Start();
- t2.Start();
- t3.Start();
- return results;
- });
- Task finalTask = parentTask.ContinueWith(parent =>
- {
- foreach (int result in parent.Result)
- {
- Console.WriteLine(result);
- }
- });
- finalTask.Wait();
- Console.ReadLine();
- }
- }
- }
- 这段代码的输出结果是: ,,
- FinalTask会等待所有子Task结束后再执行。
- TaskFactory
- 关于TaskFactory,上面的例子中我们使用了System.Threading.Tasks .Task.Factory属性来快速的创建Task。当然你也可以自己创建TaskFactory,你可以指定自己的TaskCreationOptions,TaskContinuationOptions来使得通过你的Factory创建的Task默认行为不同。
- .Net中有一些默认的创建Task的方式,由于TaskFactory创建Task的默认行为不同可能会导致一些不容易发现的问题。
- 如在.NET .5中,Task加入了一个Run的静态方法:
- Task.Run(someAction);
- 如果你用这个方法代替上面例子中的Task.Factory.StartNew,就无法得到正确的结果。原因是Task.Run创建Task的行为默认是默认是拒绝添加子任务的。上面的代码等价于:
- Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- 你也可以创建具有自己默认行为的TaskFactory。
- 无论ThreadPool也好,或者Task,微软都是在想进办法来实现线程的重用,来节省不停的创建销毁线程带来的开销。线程池内部的实现可能在不同版本中有不同的机制。如果可能的话,使用线程池来管理线程仍然是建议的选择。
- 作者:独上高楼
- 出处: http://www.cnblogs.com/myprogram/
- 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Task构造的更多相关文章
- Codeforces 959D. Mahmoud and Ehab and another array construction task(构造, 简单数论)
Codeforces 959D. Mahmoud and Ehab and another array construction task 题意 构造一个任意两个数都互质的序列,使其字典序大等于a序列 ...
- Codeforces 461D. Appleman and Complicated Task 构造,计数
原文链接https://www.cnblogs.com/zhouzhendong/p/CF461D.html 题解 首先我们可以发现如果确定了第一行,那么方案就唯一了. 然后,我们来看看一个点的值确定 ...
- cf1088C Ehab and a 2-operation task (构造)
题意:给一个数列,你可以进行至多n+1次操作,每次给一个前缀对某数取模或者加某数,使得最后数列严格单增 考虑到因为是前缀和而且还不能加负数,光靠加是不能让前面的小于后面的 所以要让他先在模某数意义下单 ...
- Codeforces - 1114B - Yet Another Array Partitioning Task - 构造 - 排序
https://codeforces.com/contest/1114/problem/B 一开始叫我做,我是不会做的,我没发现这个性质. 其实应该很好想才对,至少要选m个元素,其中m个作为最大值,从 ...
- 【kAriOJ】离散数学 构造群码 极大似然法解码
A. 编程题1 构造群码 时间限制 1000 ms 内存限制 65536 KB 题目描述 针对给定H,计算群码编码函数eH,并计算给定字的码字. 输入格式 第一行输入两个整数m,n:(m < n ...
- 【Hadoop代码笔记】Hadoop作业提交之TaskTracker获取Task
一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobClient提交的作业,并进行初始化.本文着重描述,JobTracker如何选择作业 ...
- Hadoop作业提交之TaskTracker获取Task
[Hadoop代码笔记]Hadoop作业提交之TaskTracker获取Task 一.概要描述 在上上一篇博文和上一篇博文中分别描述了jobTracker和其服务(功能)模块初始化完成后,接收JobC ...
- C#与C++的发展历程第三 - C#5.0异步编程巅峰
系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...
- C#知识点记录
用于记录C#知识要点. 参考:CLR via C#.C#并发编程.MSDN.百度 记录方式:读每本书,先看一遍,然后第二遍的时候,写笔记. CLR:公共语言运行时(Common Language Ru ...
随机推荐
- c#面向对象基础3
静态与非静态的区别 (1)在非静态类中既可以有实例成员,也可以有静态成员(static修饰). (2)在调用静态成员的时候要使用:对象名.实例成员. (3)在调用静态成员的时候要使用:类名.静态成员. ...
- JAVA Spring JavaBean 属性值的注入方式( 属性注入, 特殊字符注入 <![CDATA[ 带有特殊字符的值 ]]> , 构造器注入 )
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 1.Spring AOP (上)
转自:https://blog.csdn.net/yusheng8711/article/details/21622773 Spring有两大核心,IOC和AOP.IOC在java web项目中无时无 ...
- VBA 浏览文件夹
Private Function SelectFolder() As String With Application.FileDialog(msoFileDialogFolderPick ...
- linux查看网卡驱动
[root@hudson ~]# yum install ethtool -y [root@hudson ~]# ethtool -i em1driver: bnx2version: 2.2.3fir ...
- UGUI Auto Layout 自动布局
Layout Element 首先分配 Minimum Size 如果还有足够空间,分配 Preferred Size 如果还有额外空间,分配 Flexible Size 比较特别的是 Flexibl ...
- Numpy 基础知识
1.使用ipython --pylab 自动加载 Numpy.Scipy.Matplotlib模块. 创建数组a = arange(10) b = arange(10,dtype='f')c = ar ...
- godaddy nginx https 配置
一. 生成秘钥key,运行: $ openssl genrsa -des3 -out server.key 2048 1 会有两次要求输入密码,输入同一个即可 输入密码 然后你就获得了一个server ...
- MapReduce超时原因(Time out after 300 secs)
目前碰到过三种原因导致 Time out after 300 secs. 1. 死循环 这是最常见的原因.显式的死循环很容易定位,隐式的死循环就比较麻烦了,比如正则表达式.曾经用一个网上抄来的邮箱正则 ...
- Mysql修改密码办法
方法1: 用SET PASSWORD命令 首先登录MySQL. 格式:mysql> set password for 用户名@localhost = password('新密码'); 例子:my ...