取消
目前,以下技术支持以标准方式取消长时间运行的操作:任务、并发集合类、并行LINQ、其他集中同步机制。
取消,是协作的,它不是强迫的
长时间运行的任务会检查它是否被取消,并响应地返回控制权
支持取消的方法,接收一个
CancellationToken
参数。
- 长时间运行的操作,检查取消的方式:
IsCancellationRequested
属性- 取消标记时,使用
WaitHandle
属性 - 使用
Register
方法,接收以下参数:Action
:在取消标记时调用ICancelableOperation
,实现这个接口的对象的Cancel()
方法再执行取消操作室调用
Parallel.For() 的取消
- ParallelOptions
- CancellationToken
- 通过CancellationTokenSource来生成
- CancellationTokenSource实现了ICancelableOperation接口
- 因此,可以用CancellationToken注册, Register()方法注册取消操作时的信息
- 允许用Cancel()方法取消操作
- 因此,可以用CancellationToken注册, Register()方法注册取消操作时的信息
- CancellationTokenSource实现了ICancelableOperation接口
- 通过CancellationTokenSource来生成
- CancellationToken
- Parallel类验证CancellationToken的结果,并取消操作
- 一旦取消操作,For()就抛出一个OperationCanceledException
public static void CancelParallelFor()
{
Console.WriteLine(nameof(CancelParallelFor));
var cts = new CancellationTokenSource();
cts.Token.Register(() => Console.WriteLine("*** token cancelled"));
// send a cancel after 500 ms
cts.CancelAfter(500);
try
{
ParallelLoopResult result =
Parallel.For(0, 100, new ParallelOptions
{
CancellationToken = cts.Token,
},
x =>
{
Console.WriteLine($"loop {x} started");
int sum = 0;
for (int i = 0; i < 100; i++)
{
Task.Delay(2).Wait();
sum += i;
}
Console.WriteLine($"loop {x} finished");
});
}
catch (OperationCanceledException ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine();
}
复制代码
输出:
CancelParallelFor
loop 0 started
loop 24 started
loop 12 started
loop 36 started
loop 48 started
loop 60 started
loop 72 started
loop 84 started
loop 96 started
*** token cancelled
loop 24 finished
loop 84 finished
loop 0 finished
loop 36 finished
loop 96 finished
loop 12 finished
loop 48 finished
loop 72 finished
loop 60 finished
The operation was canceled.
复制代码