下面我将详细讲解“C#使用CancellationTokenSource取消多线程”的完整攻略。
什么是 CancellationTokenSource
CancellationTokenSource是用来控制CancellationToken的一个类型,CancellationToken是一种用于取消例如Task、ThreadPoolWaitHandle和PLINQ等等API的执行的机制。 CancellationTokenSource的主要作用是创建用于请求取消操作的 CancellationToken。
CancellationTokenSource的使用方法
创建 CancellationTokenSource
首先我们需要创建一个CancellationTokenSource才能开始操作。可以使用无参数构造函数创建默认情况下不存在任何请求取消操作的 CancellationTokenSource,也可以使用一个int类型的参数构造函数创建可以在指定的毫秒数内自动取消的 CancellationTokenSource。
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
发出取消请求
我们可以使用CancellationTokenSource对象的Cancel方法取消与之关联的所有 CancellationToken。 当取消请求发出后,与 CancellationToken 关联的任务应该立即停止执行,这样可以快速地屏蔽后续进一步的资源密集型操作。我们可以在需要的地方直接调用Cancel方法来发起取消请求。
cancellationTokenSource.Cancel();
是否收到取消请求
通过CancellationToken.IsCancellationRequested属性可以检测与 CancellationToken 关联的请求是否收到取消请求。 以下代码演示了如何执行具有取消选项的异步操作:
public async Task DoAsyncWork(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
// TODO: 执行异步操作
}
// 如果收到取消请求,立即抛出OperationCanceledException。
token.ThrowIfCancellationRequested();
}
与Task关联
现在我们需要让某个Task与CancellationToken关联,以便在取消请求发出后能够响应它们。可以使用Task的Cancellation属性来指定CancellationToken。
Task.Run(() =>
{
// TODO: 执行需要取消请求的任务
}, cancellationTokenSource.Token);
取消等待的操作
ThreadPool.WaitHandle 也支持 CancellationToken。 取消等待的操作可以通过静态WaitHandle.WaitAny(WaitHandle[], CancellationToken) 或 ThreadPool.RegisterWaitForSingleObject(WaitHandle, delegate, object, int, bool)进行。
示例1
下面是一个简单的示例。程序首先创建了一个CancellationTokenSource,然后启动一个任务,该任务将在指定的时间内循环运行,同时检查CancellationToken,在任务运行的过程中如果取消请求收到则退出循环。
static async Task CancellationTokenExample1(CancellationTokenSource cancellationTokenSource)
{
Console.WriteLine("开始任务");
try
{
// 执行异步操作,如果在指定时间内完成,就等待响应
await Task.Delay(3000, cancellationTokenSource.Token);
Console.WriteLine("任务15秒之后完成了!");
}
catch (TaskCanceledException)
{
Console.WriteLine("任务收到取消请求!");
}
Console.WriteLine("任务结束!");
}
示例2
下面是另一个更复杂的示例,演示如何使用CancellationTokenSource来取消线程池中的操作。
首先定义了一个StartTime,然后在循环中定义了每个线程池中处理的任务,并在执行任务时检查CancellationToken是否已经收到取消请求。
static void CancellationTokenExample2(CancellationTokenSource cancellationTokenSource)
{
var startTime = DateTime.UtcNow;
var handles = new[] { new AutoResetEvent(false) };
Console.WriteLine($"开始任务 {startTime:O}");
var token = cancellationTokenSource.Token;
ThreadPool.QueueUserWorkItem(_ => {
try
{
var waitTime = 1000;
Console.WriteLine($"开启线程1,等待{waitTime}秒");
while (!token.IsCancellationRequested)
{
if (DateTime.UtcNow.Subtract(startTime).Seconds > 15)
{
cancellationTokenSource.Cancel();
}
Task.Delay(waitTime, token).Wait(token); // 等待操作
Console.WriteLine($"线程1等待了{waitTime}秒后完成了它的工作。");
handles[0].Set();
}
Console.WriteLine("取消操作完成。");
}
catch (OperationCanceledException)
{
Console.WriteLine("线程1收到取消请求。");
}
}, null);
ThreadPool.RegisterWaitForSingleObject(handles[0], _ => {
try
{
var waitTime = 500;
Console.WriteLine("开启线程2,等待500毫秒");
Task.Delay(waitTime).Wait(token);
Console.WriteLine("线程2等待500毫秒后完成了它的工作。");
handles[0].Set();
}
catch (OperationCanceledException)
{
Console.WriteLine("线程2收到取消请求。");
}
}, null, TimeSpan.FromSeconds(1), false);
WaitHandle.WaitAll(handles);
Console.WriteLine("任务结束!");
}
这样就完成了使用CancellationTokenSource来取消多线程的攻略了,希望本文能够帮助到你。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 使用CancellationTokenSource取消多线程 - Python技术站