1、需求
我们知道task是并行计算的,比如说主线程在某个时刻由于某种原因要取消某个task的执行,我们能做到吗? 当然我们可以做到。
在4.0中给我们提供一个“取消标记”叫做CancellationTokenSource.Token,在创建task的时候传入此参数,就可以将主线程和任务相关联,然后在任务中设置“取消信号“叫做ThrowIfCancellationRequested来等待主线程使用Cancel来通知,一旦cancel被调用。task将会抛出OperationCanceledException来中断此任务的执行,最后将当前task的Status的IsCanceled属性设为true。
注意:一定要处理这个异常,可以通过调用Task.Result成员来获取这个异常。如果一直不查询Task的Exception属性。你的代码就永远注意不到这个异常的发生,如果不能捕捉到这个异常,垃圾回收时,抛出AggregateException,进程就会立即终止,这就是“牵一发动全身”,莫名其妙程序就自己关掉了,谁也不知道这是什么情况。所以,必须调用前面提到的某个成员,确保代码注意到异常,并从异常中恢复。因此可以将条用Task的某个成员来检查Task是否跑出了异常,通常调用Task的Result。下面看代码:
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
var ct = cts.Token;
Task task1 = new Task(() => { Run1(ct); }, ct);
Task task2 = new Task(Run2);
try
{
task1.Start();
task2.Start();
//在这段时间内,ct.ThrowIfCancellationRequested();是不会被触发的
Thread.Sleep(1000);
cts.Cancel();
//这时候会触发ct.ThrowIfCancellationRequested();
Task.WaitAll(task1, task2);
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
Console.WriteLine(\"\\nhi,我是OperationCanceledException:{0}\\n\", e.Message);
}
//task1是否取消
//Console.WriteLine(\"task1是不是被取消了? {0}\", task1.IsCanceled);
//Console.WriteLine(\"task2是不是被取消了? {0}\", task2.IsCanceled);
}
Console.WriteLine(\"task1是不是被取消了? {0}\", task1.IsCanceled);
Console.WriteLine(\"task2是不是被取消了? {0}\", task2.IsCanceled);
Console.Read();
}
static void Run1(CancellationToken ct)
{
//下面这句话是没有用的,因为这个时候没有收到Cancel的消息
ct.ThrowIfCancellationRequested();
Console.WriteLine(\"我是任务1\");
Thread.Sleep(2000);//是为了在Cancel的时候Run1没有执行完
//当上面等到1000ms多的时候实际上已经接收到Cancel的消息了,但是这个时候不会取消task的,只有调用下面这句话的时候才会取消task
ct.ThrowIfCancellationRequested();
Console.WriteLine(\"我是任务1的第二部分信息\");
}
static void Run2()
{
Console.WriteLine(\"我是任务2\");
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
注意:
1、只有ct.ThrowIfCancellationRequested();才能真正的取消Task,此外,ct.ThrowIfCancellationRequested();的调用必须是接收到Cancel命令过来才会触发的。
2、个人认为:这样子的目的是为了接收到取消的时候,不会立马停止Task,而是只有在合适的时间停止。
2、Task的写法:
var cts = new CancellationTokenSource();
var ct = cts.Token;
Task task1 = new Task(() => { Run1(ct); }, ct);
---------------------
作者:何叶
来源:CSDN
原文:https://blog.csdn.net/hxfhq1314/article/details/52652885
版权声明:本文为博主原创文章,转载请附上博文链接!
版权声明
本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。



