线程池-实现一个取消选项
代码Demo:
using System;
using System.Threading;
在Main方法下面加入以下代码片段:
static void AsyncOperation1(CancellationToken token)
{
Console.WriteLine("Starting the first task");
for (int i = 0; i < 5; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("The first task has been canceled.");
return;
}
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Console.WriteLine("The first task has completed succesfully");
}
/// <summary>
///
/// </summary>
/// <param name="token"></param>
static void AsyncOperation2(CancellationToken token)
{
try
{
Console.WriteLine("Starting the second task");
for (int i = 0; i < 5; i++)
{
token.ThrowIfCancellationRequested();
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Console.WriteLine("The second task has completed successfully");
}
catch (OperationCanceledException)//抛出OperationCanceledException异常
{
Console.WriteLine("The second task has been canceled.");
}
}
private static void AsyncOperation3(CancellationToken token)
{
bool cancellationFlag = false;
token.Register(() => cancellationFlag = true);//注册一个回调函数
Console.WriteLine("Starting the third task");
for (int i = 0; i < 5; i++)
{
if (cancellationFlag)
{
Console.WriteLine("The third task has been canceled.");
return;
}
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Console.WriteLine("The third task has completed succesfully");
}
在Main方法中加入以下代码片段:
using (var cts = new CancellationTokenSource())
{
CancellationToken token = cts.Token;
ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token));
Thread.Sleep(TimeSpan.FromSeconds(2));
cts.Cancel();
}
using (var cts = new CancellationTokenSource())
{
CancellationToken token = cts.Token;
ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token));
Thread.Sleep(TimeSpan.FromSeconds(2));
cts.Cancel();
}
using (var cts = new CancellationTokenSource())
{
CancellationToken token = cts.Token;
ThreadPool.QueueUserWorkItem(_ => AsyncOperation3(token));
Thread.Sleep(TimeSpan.FromSeconds(2));
cts.Cancel();
}
Thread.Sleep(TimeSpan.FromSeconds(2));
工作原理:
本节中介绍了CancellationTokenSource和CancellationToken两个新类。他们在.NET4.0被引入,目前是实现异步操作的取消操作的事实标准。由于线程池已经存在了很长时间,并没有特殊的API来实现取消标记功能,但是仍然可以对线程池使用上述API。
在本程序中使用了三种方式来实现取消过程。第一个是轮询来检查CancellationToken.IsCancellationRequested属性。如果该属性为true,则说明操作需要被取消,我们必须放弃该操作。
第二种方式是跑出一个OperationCanceledException异常。这允许在操作之外控制取消过程,即需要取消操作时,通过操作之外的代码来处理。
最后一种方式是注册一个回调函数。当操作被取消时。,在线程池将调用该回调函数。这允许链式传递一个取消逻辑到另一个异步操作中。