C#CancellationToken和CancellationTokenSource的用法详解

更新时间:2023-07-08 07:28:57 阅读: 评论:0

C#CancellationToken和CancellationTokenSource的⽤法
详解
⽬录
CancellationToken
通过Register⽅法注册的服务只会执⾏⼀次!
CancellationTokenSource
使⽤场景⼀
使⽤场景⼆
使⽤场景三
CancellationToken
  CancellationToken有⼀个构造函数,可以传⼊⼀个bool类型表⽰当前的CancellationToken是否是取消状态。另外,因为CancellationToken是⼀个结构体,所以它还有⼀个空参数的构造函数。 
public CancellationToken();//因为是结构体,才有空构造函数,不过没什么作⽤
public CancellationToken(bool canceled);
   属性如下: 
//静态属性,获取⼀个空的CancellationToken,这个CancellationToken注册的回调⽅法不会被触发,作⽤类似于使⽤空构造函数得到的CancellationToken    public static CancellationToken None { get; }
//表⽰当前CancellationToken是否可以被取消
public bool CanBeCanceled { get; }
//表⽰当前CancellationToken是否已经是取消状态
public bool IsCancellationRequested { get; }
//和CancellationToken关联的WaitHandle对象,CancellationToken注册的回调⽅法执⾏时通过这个WaitHandle实现的
public WaitHandle WaitHandle { get; }
  常⽤⽅法: 
//往CancellationToken中注册回调
public CancellationTokenRegistration Register(Action callback);
public CancellationTokenRegistration Register(Action callback, bool uSynchronizationContext);
public CancellationTokenRegistration Register([NullableAttribute(new[] { 1, 2 })] Action<object?> callback, object? state);
public CancellationTokenRegistration Register([NullableAttribute(new[] { 1, 2 })] Action<object?> callback, object? state, bool uSynchronizationContext);    //当CancellationToken处于取消状态是,抛出System.OperationCanceledException异常
public void ThrowIfCancellationRequested();
  常⽤的注册回调的⽅法是上⾯4个Register⽅法,其中callback是回调执⾏的委托,uSynchronizationContext表⽰是否使
⽤同步上下⽂,state是往回调委托中传的参数值
  另外,Register⽅法会返回⼀个CancellationTokenRegistration结构体,当注册回调之后,可以调⽤CancellationTokenRegistration的Unregister⽅法来取消注册,这个Unregister⽅法会返回⼀个bool值,当成功取消时返回true,当取消失败(⽐如回调已执⾏)将返回fal: 
国有企业党建
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var cancellationTokenRegistration = cancellationTokenSource.Token.Register(() =>
{
Console.WriteLine("Canceled");//这⾥将不会执⾏输出
});
//cancellationTokenSource.Cancel();
//var result = cancellationTokenRegistration.Unregister();//result = fal
var result = cancellationTokenRegistration.Unregister();//result = true
  cancellationTokenSource.Cancel();
  上⾯提到,CancellationToken可以使⽤构造函数直接构造,同时可以传⼊⼀个参数,表⽰当前的状态,需要注意的
是,CancellationToken的状态最多可以改变⼀次,也就是从未取消变成已取消。
  如果构造时传⼊true,也就是说CancellationToken是已取消状态,这个时候注册的回调都会⽴即执⾏: 
CancellationToken cancellationToken = new CancellationToken(true);
cancellationToken.Register(() =>
{
Console.WriteLine("Canceled");//这⾥会⽴即执⾏输出Canceled
});
  但如果构造时传⼊的是fal,说明CancellationToken处于未取消状态,这时候注册的回到都会处于⼀个待触发状态:
CancellationToken cancellationToken = new CancellationToken(fal);
cancellationToken.Register(() =>
{
Console.WriteLine("Canceled");//这⾥不会⽴即执⾏输出
});
通过Register⽅法注册的服务只会执⾏⼀次!
  但⼀般的,如果传⼊fal构造出来的CancellationToken,可以认为是不会触发的,因为它没有触发的⽅法!所以⼀般的,我们都不会直接使⽤构造函数创建CancellationToken,⽽是使⽤CancellationTokenSource对象来获取⼀个CancellationToken
CancellationTokenSource
  CancellationTokenSource可以理解为CancellationToken的控制器,控制它什么时候变成取消状态的⼀个对象,它有⼀个CancellationToken类型的属性Token,只要CancellationTokenSource创建,这个Token也会被创建,同时Token会和这个CancellationTokenSource绑定
//表⽰Token是否已处于取消状态
public bool IsCancellationRequested { get; }
//CancellationToken 对象
public CancellationToken Token { get; }
  可以直接创建⼀个CancellationTokenSource对象,同时指定⼀个时间段,当过了这段时间后,CancellationTokenSource 就会⾃动取消了。
  CancellationTokenSource的取消有4个⽅法: 
//⽴刻取消
public void Cancel();
//⽴刻取消
public void Cancel(bool throwOnFirstException);
海豚介绍//延迟指定时间后取消
public void CancelAfter(int millicondsDelay);清理淤泥
//延迟指定时间后取消
public void CancelAfter(TimeSpan delay);
  Cancel和两个CancelAfter⽅法没什么特别的,主要就是有⼀个延迟的效果,需要注意的是Cancel的两个重载之间的区别。
  ⾸先,上⾯说道,CancellationToken状态只能改变⼀次(从未取消变成已取消),当CancellationToken时已取消状态时,每次往其中注册的回调都会⽴刻执⾏!当处于未取消状态时,注册进去的回调都会等待执⾏。
  需要注意的是,当在未取消状态下注册多个回调时,它们在执⾏时是⼀个类似栈的结构顺序,先注册后执⾏。
  ⽽CancellationToken的Register可以注册多个回调,那他们可能都会抛出异常,throwOnFirstException参数表⽰在第⼀次报错时的处理⾏为.
  throwOnFirstException = true 表⽰⽴即抛出当前发⽣的异常,后续的回调将会取消执⾏ 
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
try
{
cancellationTokenSource.Token.Register(() =>
{
throw new Exception("1");小米粥怎么做好吃
});
cancellationTokenSource.Token.Register(() =>
{
throw new Exception("2");//不会执⾏
});
cancellationTokenSource.Cancel(true);
}
catch (Exception ex)
{
//ex is System.Exception("1")
}
  throwOnFirstException = fal 表⽰跳过当前回调的异常,继续执⾏⽣效的回调,等所有的回调执⾏完成之后,再将所有的异常打包成⼀个System.AggregateException异常抛出来!
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
try
{
cancellationTokenSource.Token.Register(() =>
{
throw new Exception("1");女儿婚礼父亲讲话
});
cancellationTokenSource.Token.Register(() =>
{
throw new Exception("2");
});
cancellationTokenSource.Cancel(fal);//相当于cancellationTokenSource.Cancel()
}
catch (Exception ex)
{
/
/ex is System.AggregateException:[Exception("2"),Exception("1")]
}
  CancellationTokenSource还可以与其它CancellationToken关联起来,⽣成⼀个新的CancellationToken,当其他CancellationToken取消时,会⾃动触发当前的CancellationTokenSource执⾏取消动作! 
如何规划自己的人生使⽤场景⼀
  当我们创建异步操作时,可以传⼊⼀个CancellationToken,当异步操作处于等待执⾏状态时,可以通过设置CancellationToken为取消状态将异步操作取消执⾏: 
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var task = new Task(() =>
{
Thread.Sleep(1500);//执⾏了2秒中代码
Console.WriteLine("Execute Some Code");
}, cancellationTokenSource.Token);
task.Start();//启动,等待调度执⾏
//发现不对,可以取消task执⾏
cancellationTokenSource.Cancel();
Thread.Sleep(1000);//等待1秒
Console.WriteLine("Task状态:" + task.Status);//Canceled
  但是经常的,我们的取消动作可能不会那么及时,如果异步已经执⾏了,再执⾏取消时⽆效的,这是就需要我们⾃⼰在异步委托中检测了: 
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
var task = new Task(() =>
{
Thread.Sleep(1500);//执⾏了2秒中代码
cancellationTokenSource.Token.ThrowIfCancellationRequested();
Console.WriteLine("Execute Some Code");
}, cancellationTokenSource.Token);
task.Start();//启动,等待调度执⾏
Thread.Sleep(1000);////⼀段时间后发现不对,可以取消task执⾏
cancellationTokenSource.Cancel();
Thread.Sleep(1000);//等待1秒
Console.WriteLine("Task状态:" + task.Status);//Canceled
使⽤场景⼆
  有时,我们希望在触发某个时间后,可以执⾏某些代码功能,但是在异步环境下,我们不能保证那
些要执⾏的代码是否已准备好了,⽐如我们有⼀个Clo⽅法,当调⽤Clo后表⽰是关闭状态,如果我们相当程序处于关闭状态时执⾏⼀些通知,⼀般的,我们可能是想到采⽤事件模型,或者在Clo⽅法传⼊事件委托,或者采⽤⼀些诸如模板设计这样的模型去实现: 
class Demo
{
public void Clo(Action callback)
{
//关闭
Thread.Sleep(3000);
callback?.Invoke();//执⾏通知
}
}
  或者 
class Demo
{
public event Action Callback;
public void Clo()
{
//关闭
Thread.Sleep(3000);
Callback?.Invoke();//执⾏通知
}
}
  但是这就有问题了,如果是传⼊参数或者采⽤事件模型,因为前⾯说过了,如果在异步环境下,我们不能保证那些要执⾏的代码是否已准备好了,也许在执⾏Clo⽅法时,程序还未注册回调。
  这个时候就可以使⽤CancellationToken来解决这个问题: 
  主需要往Token属性中注册回调⽽⽆需关注Clo什么时候执⾏了
使⽤场景三
  有时候,我们写⼀个异步⽆限循环的⽅法去处理⼀些问题,⽽我们希望可以在⽅法外来停⽌它这个时候,我们就可以通过返回CancellationTokenSource来实现了: 
public CancellationTokenSource Listen()
{
楷书钢笔字帖CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
//循环调度执⾏
Task.Run(() =>
{
while (true)
{
cancellationTokenSource.Token.ThrowIfCancellationRequested();
//循环执⾏⼀些操作
Thread.Sleep(1000);
Console.WriteLine("Run");
}
});
return cancellationTokenSource;
我的老师300字作文}
以上就是C# CancellationToken和CancellationTokenSource的⽤法详解的详细内容,更多关于C# CancellationToken和CancellationTokenSource的资料请关注其它相关⽂章!

本文发布于:2023-07-08 07:28:57,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1072645.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:取消   状态   注册   回调   处于   触发   模型   属性
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图