如何正确地吐槽使用 Task.ContinueWith

拒绝访问 | www. | 百度云加速
请打开cookies.
此网站 (www.) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(38d340cab30a436a-ua98).
重新安装浏览器,或使用别的浏览器& & &在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于
&任务的编程模型&所冲击,因为task会比thread具有更小的性能开销,不过大家肯定会有疑惑,任务和线程到底有什么区别?
1:任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。
2:任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小
& & & 的开销和精确的控制。
1. 最简单的使用
& 开启task有两种方式:
&1& 实例化Task
//第一种方式开启2
var task1 = new Task(() =&3
&2&从工厂中创建
var task2 = Task.Factory.StartNew(() =&2
是的,同样两种方法都可以创建,我们肯定会想两者是不是多多少少有点区别呢?好的,下面我们举个例子看分晓。
1 using S 2 using System.T 3 using System.Threading.T 4 using System.D 5 using System.Collections.G 6
7 class Program 8 { 9
static void Main(string[] args)10
//第一种方式开启12
var task1 = new Task(() =&13
//第二种方式开启18
var task2 = Task.Factory.StartNew(() =&19
Console.WriteLine("调用start之前****************************\n");24 25
//调用start之前的&任务状态&26
Console.WriteLine("task1的状态:{0}", task1.Status);27 28
Console.WriteLine("task2的状态:{0}", task2.Status);29 30
task1.Start();31 32
Console.WriteLine("\n调用start之后****************************");33 34
//调用start之前的&任务状态&35
Console.WriteLine("\ntask1的状态:{0}", task1.Status);36 37
Console.WriteLine("task2的状态:{0}", task2.Status);38 39
//主线程等待任务执行完40
Task.WaitAll(task1, task2);41 42
Console.WriteLine("\n任务执行完后的状态****************************");43 44
//调用start之前的&任务状态&45
Console.WriteLine("\ntask1的状态:{0}", task1.Status);46 47
Console.WriteLine("task2的状态:{0}", task2.Status);48 49
Console.Read();50
static void Run1()53
Thread.Sleep(1000);55
Console.WriteLine("\n我是任务1");56
static void Run2()59
Thread.Sleep(2000);61
Console.WriteLine("我是任务2");62
①:从图中可以看出两种task实例的简略生命周期。
Created:表示默认初始化任务,但是我们发现&工厂创建的&实例直接跳过。
WaitingToRun: 这种状态表示等待任务调度器分配线程给任务执行。
RanToCompletion:任务执行完毕。
②:我们发现task的使用跟Thread很相似,就连waitAll的方法使用也一样,刚才也说了,任务是架构在线程之上,那么我们用VS里面的
& & & &并行任务&看一看,快捷键Ctrl+D,K,或者找到&调试"-&"窗口&-&"并行任务&,我们在WaitAll方法处插入一个断点,最终我们发现
& & & 任务确实托管给了线程。
2. 取消任务
& &我们知道task是并行计算的,比如说主线程在某个时刻由于某种原因要取消某个task的执行,我们能做到吗? 当然我们可以做到。
在4.0中给我们提供一个&取消标记&叫做CancellationTokenSource.Token,在创建task的时候传入此参数,就可以将主线程和任务相
关联,然后在任务中设置&取消信号&叫做ThrowIfCancellationRequested来等待主线程使用Cancel来通知,一旦cancel被调用。task将会
抛出OperationCanceledException来中断此任务的执行,最后将当前task的Status的IsCanceled属性设为true。看起来是不是很抽象,
没关系,上代码说话。
1 using S 2 using System.T 3 using System.Threading.T 4 using System.D 5 class Program 6 { 7
static void Main(string[] args) 8
var cts = new CancellationTokenSource();10
var ct = cts.T11 12
Task task1 = new Task(() =& { Run1(ct); }, ct);13 14
Task task2 = new Task(Run2);15 16
task1.Start();19
task2.Start();20 21
Thread.Sleep(1000);22 23
cts.Cancel();24 25
Task.WaitAll(task1, task2);26
catch (AggregateException ex)28
foreach (var e in ex.InnerExceptions)30
Console.WriteLine("\nhi,我是OperationCanceledException:{0}\n", e.Message);32
//task1是否取消35
Console.WriteLine("task1是不是被取消了? {0}", task1.IsCanceled);36
Console.WriteLine("task2是不是被取消了? {0}", task2.IsCanceled);37
Console.Read();40
static void Run1(CancellationToken ct)43
ct.ThrowIfCancellationRequested();45 46
Console.WriteLine("我是任务1");47 48
Thread.Sleep(2000);49 50
ct.ThrowIfCancellationRequested();51 52
Console.WriteLine("我是任务1的第二部分信息");53
static void Run2()56
Console.WriteLine("我是任务2");58
从图中可以看出
①:Run1中的Console.WriteLine("我是任务1的第二部分信息"); 没有被执行。
②:Console.WriteLine("task1是不是被取消了? {0}", task1.IsCanceled); 状态为True。
也就告诉我们Run1中途被主线程中断执行,我们coding的代码起到效果了。
3. 获取任务的返回值
& 我们以前写线程的时候注册的方法一般都是void类型,如果主线程要从工作线程中获取数据一般采用的手段是&委托+事件&的模式,然而
在Task中有两种方式可以解决。
&1& &现在我们的实例化是采用Task&TResult&的形式,其中TResult就是当前task执行后返回的结果,下面举得例子是t2任务获取
& & & & &t1的执行结果。
1 using S 2 using System.T 3 using System.Threading.T 4 using System.D 5 using System.Collections.G 6
7 class Program 8 { 9
static void Main(string[] args)10
//执行task112
var t1 = Task.Factory.StartNew&List&string&&(() =& { return Run1(); });13 14
t1.Wait();15 16
var t2 = Task.Factory.StartNew(() =&17
Console.WriteLine("t1集合中返回的个数:" + string.Join(",", t1.Result));19
Console.Read();22
static List&string& Run1()25
return new List&string& { "1", "4", "8" };27
&2&采用ContinueWith方法,很有意思,现在我们将上面的方法改造一下。
1 using S 2 using System.T 3 using System.Threading.T 4 using System.D 5 using System.Collections.G 6
7 class Program 8 { 9
static void Main(string[] args)10
//执行task112
var t1 = Task.Factory.StartNew&List&string&&(() =& { return Run1(); });13 14
var t2 = t1.ContinueWith((i) =&15
Console.WriteLine("t1集合中返回的个数:" + string.Join(",", i.Result));17
Console.Read();20
static List&string& Run1()23
return new List&string& { "1", "4", "8" };25
4:ContinueWith结合WaitAll来玩一把
& & 当这两者结合起来,我们就可以玩一些复杂一点的东西,比如说现在有7个任务,其中t1需要串行,t2-t3可以并行,t4需要串行,t5-t6并行,
好了,我们上一下代码说话,下面代码没有实际意思,纯属演示。
1 using S 2 using System.T 3 using System.Threading.T 4 using System.D 5 using System.Collections.G 6 using System.Collections.C 7
8 class Program 9 {10
static void Main(string[] args)11
ConcurrentStack&int& stack = new ConcurrentStack&int&();13 14
//t1先串行15
var t1 = Task.Factory.StartNew(() =&16
stack.Push(1);18
stack.Push(2);19
//t2,t3并行执行22
var t2 = t1.ContinueWith(t =&23
stack.TryPop(out result);27
//t2,t3并行执行30
var t3 = t1.ContinueWith(t =&31
stack.TryPop(out result);35
//等待t2和t3执行完38
Task.WaitAll(t2, t3);39 40 41
//t4串行执行42
var t4 = Task.Factory.StartNew(() =&43
stack.Push(1);45
stack.Push(2);46
//t5,t6并行执行49
var t5 = t4.ContinueWith(t =&50
stack.TryPop(out result);54
//t5,t6并行执行57
var t6 = t4.ContinueWith(t =&58
//只弹出,不移除62
stack.TryPeek(out result);63
//临界区:等待t5,t6执行完66
Task.WaitAll(t5, t6);67 68
//t7串行执行69
var t7 = Task.Factory.StartNew(() =&70
Console.WriteLine("当前集合元素个数:" + stack.Count);72
Console.Read();75
阅读(...) 评论()Task。ContinueWith,如何正确地使用_学习帮助_识作业百解网
Task。ContinueWith,如何正确地使用
编辑: 识作业百解网 &&&来源:用户发布&&&发布时间:&&&查看次数:42
帮帮我,Task照了。ContinueWith,如何正确地使用?谢咯!
【探讨解答】
如何正确地使用Task.ContinueWith
public static void Main(string[] args) { Task.Factory.StartNew(Calculate).ContinueWith(task =& { Console.WriteLine("Finished!"); }); Console.WriteLine("Press ENTER to close..."); Console.ReadLine(); } 你会看到 按 ENTER 键关闭.....
如何正确地使用Task.ContinueWith
正确地使用 Task.ContinueWith 当试图测试第三方物流时,我遇到一个简单的问题。我想要数字 (从 1 到 1000年),例如在控制台窗口中。 这是我的代码: class Program { static void Main(string[] args) { Task.Factory.StartNew(Calculate).Co...
如何正确地使用Task.ContinueWith
public static void Main(string[] args) { Task.Factory.StartNew(Calculate).ContinueWith(task =& { Console.WriteLine("Finished!"); }); Console.WriteLine("Press ENTER to close..."); Console.ReadLine(); } 你会看到 按 ENTER 键关闭.....
如何正确地使用Task.ContinueWith
public static void Main(string[] args) { Task.Factory.StartNew(Calculate).ContinueWith(task =& { Console.WriteLine("Finished!"); }); Console.WriteLine("Press ENTER to close..."); Console.ReadLine(); } 你会看到 按 ENTER 键关闭.....
学习帮助相关
更多相关内容
本站内容来自网友发布,本站无法保证其部分内容的正确性,请用户一定仔细辨别。
[] &&[联系QQ:885&971&98] &
黑ICP备号&2552人阅读
void Main()
//前3百万个整数(从2)开始中的素数个数
Task&int& primeNumberTask = Task.Run(()=&
Enumerable.Range(2,3000000).Count(n=&
Enumerable.Range(2,(int)Math.Sqrt(n)-1).All(i=&n%i &0)));
Console.WriteLine("Task running...");
//判断异步调用是否完成,持续显示*,直到任务完成
IAsyncResult asyncResult = (IAsyncResult)primeNumberTask;
while (!asyncResult.IsCompleted)
Console.Write("*");
Thread.Sleep(100);
//打印执行结果
Console.WriteLine("\r\n线程执行结果: " + primeNumberTask.Result);
//任务完成后执行的动作
primeNumberTask.GetAwaiter().OnCompleted(()=&{
Console.WriteLine("线程执行完毕");
primeNumberTask.ContinueWith(x=& Console.WriteLine("线程执行完后,延续做一些事!" + x.Result));
为避免在VS中建项目的麻烦,直接在LinqPad中编译看结果
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4261087次
积分:58848
积分:58848
排名:第44名
原创:1195篇
转载:573篇
评论:1093条
(1)(1)(1)(4)(2)(2)(1)(1)(2)(1)(1)(3)(3)(1)(5)(1)(2)(3)(3)(4)(6)(8)(12)(3)(7)(1)(2)(8)(5)(2)(2)(1)(2)(2)(10)(9)(9)(2)(12)(10)(3)(6)(4)(3)(4)(16)(5)(12)(12)(7)(20)(25)(24)(10)(7)(4)(2)(4)(34)(12)(2)(6)(6)(1)(2)(4)(1)(8)(28)(9)(3)(3)(3)(5)(4)(2)(5)(2)(2)(3)(2)(1)(3)(3)(3)(2)(3)(2)(16)(7)(4)(10)(3)(8)(10)(11)(47)(151)(158)(11)(12)(47)(16)(16)(87)(71)(65)(164)(89)(61)(14)(10)(12)(19)(6)(5)(18)(14)(21)(11)(31)(20)(30)(4)(2)(1)(6)

我要回帖

更多关于 如何正确地选择供应商 的文章

 

随机推荐