
这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来。
这里主要讲解下CancellationTokenSource,CancellationTokenSource是用于取消线程,具体使用起来有点另类:首先定义实体,然后将其下的属性ToKen传递给线程,当需要取消线程时,调用下Cancel()方法。例子我依然采用了MSDN的例子,但我做了一些修改,这个例子虽然看起来挺复杂,但还是记录了许多内容。
由于不好理解,我就粗略讲解下:
Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(), 上面是创建任务,创建10个线程,并且线程中增加了判断,如果随即数等于0就取消该线程。
再介绍下factory.ContinueWhenAll,他包含两个参数Task[] tasks,
Action<Task[]> continuationAction。MSDN的解释是:
ContinueWhenAll 方法执行 continuationAction 委托,在 tasks 数组的所有任务完成后,无论它们的完成状态。
MSDN上就这个翻译的还不错,其他的基本可以无视了。。。
继续看代码,代码中增加了try catch,这是为什么呢,看下ContinueWhenAll英文解释:
The exception that is thrown when the tasks array is empty
这里千万不能看中文解释,不然你会凌乱的。看了英文解释就懂了,让任务为空就抛异常。
那么为什么任务为空呢,因为任务已经被取消了啊,所以为空了。具体代码如下。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Random rnd = new Random();
Object lockObj = new Object();
List<Task<int[]>> tasks = new List<Task<int[]>>();
TaskFactory factory = new TaskFactory(token);
for (int taskCtr = ; taskCtr <= ; taskCtr++)
{
int iteration = taskCtr + ;
tasks.Add(factory.StartNew(() =>
{
int value;
int[] values = new int[];
for (int ctr = ; ctr <= ; ctr++)
{
lock (lockObj)
{
value = rnd.Next(, );
}
if (value == )
{
source.Cancel();
Console.WriteLine("Cancelling at task {0}", iteration);
break;
} values[ctr - ] = value;
}
Console.WriteLine("NO Cancel at task {0}", iteration);
return values;
}, token));
}
try
{
Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(),
(results) =>
{
Console.WriteLine("Calculating overall mean...");
long sum = ;
int n = ;
foreach (var t in results)
{
foreach (var r in t.Result)
{
sum += r;
n++;
}
}
return sum / (double)n;
}, token);
Console.WriteLine("The mean is {0}.", fTask.Result);
}
catch (AggregateException ae)
{
foreach (Exception e in ae.InnerExceptions)
{
if (e is TaskCanceledException)
Console.WriteLine("Unable to compute mean: {0}",
((TaskCanceledException)e).Message);
else
Console.WriteLine("Exception: " + e.GetType().Name);
}
}
Console.ReadLine(); }
}
显示结果图片,每次的结果都不一样的,所以我也是运行了好几次,看这个结果会发现一件事,线程只执行了两个,即当线程2中调用Cancel后,其他线程也被取消了。
----------------------------------------------------------------------------------------------------
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!