取消任务-CancellationToken
1.创建CancellationToken
1.1由用户创建的CancellationTokenSource获取(推荐)
每一个CancellationTokenSource都有自己的CancellationToken,CancellationTokenSource的作用是发出取消请求,被发出请求的代码持有。CancellationToken的作用是响应取消请求,被可以被停止的代码持有。
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token=tokenSource.Token;
1.2CancellationToken构造函数或者CancellationToken.None创建
这样创建出来的CancellationToken在创建之初就处于未取消或已取消状态,并将一直保持此状态无法改变,在少数情况下会用到。
CancellationToken token = new CancellationToken();
CancellationToken token = CancellationToken.None;
2.几种取消方式
2.1超时取消
获取若干次网站内容,超过一定时间取消任务。
static async Task Main(string[] args)
{
//方式1
CancellationTokenSource tokenSource = new CancellationTokenSource(3000);
/*方式2
CancellationTokenSource tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(3000);
*/
CancellationToken token = tokenSource.Token;
Console.WriteLine(DateTime.Now);
await DownloadAsync("https://www.youzack.com", 100, token);
}
static async Task DownloadAsync(string url, int count, CancellationToken token)
{
using (HttpClient c = new HttpClient())
{
for (int i = 0; i < count; i++)
{
string html = await c.GetStringAsync(url);
Console.WriteLine(DateTime.Now);
//方式一,检测到取消请求,抛出异常
token.ThrowIfCancellationRequested();
/*方式二,属性判断token是否处于取消状态,跳出循环
if(token.IsCancellationRequested)
{
Console.WriteLine("请求取消!");
break;
}
*/
}
}
}
ThrowIfCancellationRequested
方式的执行结果:;
IsCancellationRequested
方式的执行结果:
2.1 某些API的异步方法中直接传递CancellationToken
api内部处理取消请求,可能机制更完善,比我们自己判断来处理的更及时。当一个请求耗时时长超过了设定的超时取消时长,就会出现取消不及时的情况。
static async Task DownloadAsync(string url, int count, CancellationToken token)
{
using (HttpClient client = new HttpClient())
{
for (int i = 0; i < count; i++)
{
HttpResponseMessage response = await client.GetAsync(url, token);
if (!response.IsSuccessStatusCode)
throw new Exception("Failed to get web data.");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(DateTime.Now);
}
}
}
2.3 手动取消
static async Task Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
DownloadAsync("https://www.youzack.com", 100, token);
while(Console.ReadLine()!="q")
{ }
tokenSource.Cancel();
Console.ReadLine();
}
2.4取消的回调方法
CancellationTokenSource Source = new CancellationTokenSource();
Source.Token.Register(() =>
{
Console.WriteLine("当前的Source已经被取消");
});
Task T = Task.Factory.StartNew(() =>
{
while (!Source.IsCancellationRequested)
{
Thread.Sleep(100);
Console.WriteLine("当前Thread正在运行{0}", Thread.CurrentThread.ManagedThreadId);
}
}, Source.Token);
Thread.Sleep(1000);
Source.Cancel();
2.5组合取消
//只要一个被取消,comineSource的组合就被取消,类似于WhenAny
CancellationTokenSource Source = new CancellationTokenSource();
Source.Cancel();
CancellationTokenSource Source2 = new CancellationTokenSource();
//comineSource 里面只要有一个被取消了,comineSource的状态就被取消
var comineSource = CancellationTokenSource.CreateLinkedTokenSource(Source.Token, Source2.Token);
Console.WriteLine("s1={0},s2={1},s3={2}", Source.IsCancellationRequested, Source2.IsCancellationRequested, comineSource.IsCancellationRequested);
2.6总结
cts.Cancel():只是设置一个状态,也就是设置cts.IsCancellationRequested为ture。
cts.Token.ThrowIfCancellationRequested():检查cts.IsCancellationRequested是否为true,如果为 true就抛出一个异常,从而终止线程的执行。
和以下代码同理:
if (token.IsCancellationRequested)
{
new OperationCanceledException();
}
3..Net Core MVC 框架提供的CancellationToken
//提供CancellationToken的重载
public async Task<IActionResult> Index(CancellationToken token)
{
await DownloadAsync("https://www.youzack.com", 100, token);
return View();
}
static async Task DownloadAsync(string url, int count, CancellationToken token)
{
using (HttpClient client = new HttpClient())
{
for (int i = 0; i < count; i++)
{
HttpResponseMessage response = await client.GetAsync(url, token); ;
string result = await response.Content.ReadAsStringAsync(); ;
Debug.WriteLine(DateTime.Now);
}
}
}
跳转到其他网页可取消请求:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!