博客
关于我
取消任务
阅读量:398 次
发布时间:2019-03-05

本文共 3259 字,大约阅读时间需要 10 分钟。

取消请求与CancellationToken的应用手册

在编写异步代码时,CancellationToken是一个强大的工具,能够帮助我们在不影响已有任务执行的前提下,取消正在进行的操作。以下将详细探讨如何在不同场景中使用CancellationToken,以及如何正确处理取消请求。

1. 取消请求

CancellationToken提供了一种机制,允许我们在不影响主任务的前提下,取消某些阻塞式操作。以下是一个简单的示例:

public static int CancelableMethod(CancellationToken cancellationToken)
{
for (int i = 0; i != 100000; ++i)
{
Thread.Sleep(1);
if (i % 1000 == 0)
cancellationToken.ThrowIfCancellationRequested();
}
return 42;
}

在以上代码中,cancellationToken.ThrowIfCancellationRequested()会在每1000次迭代时检查取消请求。如果取消请求已被触发,会抛出TaskCanceledException,终止当前任务。

2. 超时后取消

为了在特定时间后自动取消任务,可以使用CancellationTokenSourceCancelAfter方法。例如:

public static async Task IssueTimeoutAsync()
{
Stopwatch sw = Stopwatch.StartNew();
try
{
var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(2));
await Task.Delay(TimeSpan.FromSeconds(4), token);
}
finally
{
System.Console.WriteLine($"{sw.ElapsedMilliseconds}ms");
}
}

在这个示例中,cts.CancelAfter(TimeSpan.FromSeconds(2))会在2秒后自动取消任务。无论任务是否完成,sw.ElapsedMilliseconds都会记录总耗时。

3. 取消并行操作

在并行执行任务时,可以使用Parallel.ForEach并传递CancellationToken,以便在某些任务完成时立即取消所有相关任务:

public static void RotateMatrices(IEnumerable
matrices, float degrees, CancellationToken token)
{
Parallel.ForEach(matrices, new ParallelOptions
{
CancellationToken = token
}, matrix => matrix.Rotate(degrees));
}

在这种情况下,如果主任务被取消,token会传播到所有正在执行的并行任务,导致它们提前终止。

4. 取消响应式代码

在响应式编程中,CancellationToken可以用来控制流程。例如:

public static async Task RunGetWithTimeoutAsync()
{
CancellationTokenSource source = new CancellationTokenSource();
await GetWithTimeoutAsync("http://www.baidu.com", source.Token);
}
public static async Task
GetWithTimeoutAsync(string url, CancellationToken cancellationToken)
{
var client = new HttpClient();
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
cts.CancelAfter(TimeSpan.FromMilliseconds(100));
var combinedToken = cts.Token;
return await client.GetAsync(url, combinedToken);
}
}

在这个示例中,CreateLinkedTokenSource创建了一个关联的取消 token源。CancelAfter方法在100毫秒后自动取消请求,避免长时间等待。

5. 与其他取消体系的互操作

有时,我们需要将非标准化的取消机制与CancellationToken集成。例如:

public static async Task RunPingAsync()
{
var cts = new CancellationTokenSource();
var task = PingAsync("192.168.0.101", cts.Token);
//cts.Cancel();
await task;
}
public static async Task
PingAsync(string hostNameOrAddress, CancellationToken cancellationToken)
{
Stopwatch sw = Stopwatch.StartNew();
try
{
var ping = new Ping();
using (cancellationToken.Register(() => ping.SendAsyncCancel()))
{
return await ping.SendPingAsync(hostNameOrAddress);
}
}
finally
{
System.Console.WriteLine($"{sw.ElapsedMilliseconds}ms");
}
}

在这个示例中,cancellationToken.Register注册了一个回调函数,用于在取消请求时调用ping.SendAsyncCancel()。确保在不再需要使用回调函数时,及时释放它以避免内存泄漏。

注意事项

  • 在使用CancellationToken时,始终确保取消回调函数在不再需要时被释放,以避免内存泄漏。
  • CancellationTokenSource中使用CancelAfterCreateLinkedTokenSource是最简单且高效的方式来实现自动取消。
  • 对于外部系统或旧有代码,确保它们能够处理CancellationToken,可能需要在必要时添加适配层。

通过以上方法,可以灵活地控制异步任务的执行,并在需要时安全地终止不必要的操作。

转载地址:http://pbozz.baihongyu.com/

你可能感兴趣的文章
Nessus漏洞扫描教程之配置Nessus
查看>>
Nest.js 6.0.0 正式版发布,基于 TypeScript 的 Node.js 框架
查看>>
NetApp凭借领先的混合云数据与服务把握数字化转型机遇
查看>>
NetBeans IDE8.0需要JDK1.7及以上版本
查看>>
netcat的端口转发功能的实现
查看>>
netfilter应用场景
查看>>
netlink2.6.32内核实现源码
查看>>
Netpas:不一样的SD-WAN+ 保障网络通讯品质
查看>>
NetScaler的常用配置
查看>>
netsh advfirewall
查看>>
NETSH WINSOCK RESET这条命令的含义和作用?
查看>>
Netty WebSocket客户端
查看>>
netty 主要组件+黏包半包+rpc框架+源码透析
查看>>
Netty 异步任务调度与异步线程池
查看>>
Netty中集成Protobuf实现Java对象数据传递
查看>>
Netty事件注册机制深入解析
查看>>
Netty原理分析及实战(四)-客户端与服务端双向通信
查看>>
Netty客户端断线重连实现及问题思考
查看>>
Netty工作笔记0006---NIO的Buffer说明
查看>>
Netty工作笔记0007---NIO的三大核心组件关系
查看>>