当前位置:首页 > Web开发 > 正文

因此CancellationChangeToken只是对CancellationToken的包装

2024-03-31 Web开发

一个东西A,但愿它的某些状态在产生转变时通知到B(或C、D),
常见的做法是在A中界说一个事件(或直接用委托),,当状态转变时A去触发这个事件。而B直接订阅这个事件

技术图片

 

这种设计有点问题
B由于要订阅A的事件,所以B得完全引用A,其实有时候没须要,因为我只关心A的状态变革而已
状态变换通知这种场景很多,有没有更通用的方法呢?

解决思路

有个谁说的碰到问题加其中间层就解决了,如果解决不了就再加一层

技术图片

A和B都引用ChangeToken,
B向ChangeToken注册一个委托说:将来你有变革时回调我这个委托
当A的状态变革时会挪用ChangeToken的一个要领,这个要领内部就会去触发执行B之前塞进去的委托
此时好比有组件C、D、E..都关心A的状态变革,也可以引用ChangeToken,并向其注书籍身的委托
这样ChangeToken可以作为一个通用组件,在很多需要变动通知是场景中使用,如:asp.net core的配置系统、终结点路由、 ....

实现

微软界说了一个IChangeToken
HasChanged:暗示当前这个ChangeToken是否变革过了
ActiveChangeCallbacks:当 A触发ChangeToken产生变革时是否主动回调B塞进来的委托
RegisterChangeCallback(Action<object> callback, object state):供给一个要领,允许挪用方塞入委托,B就是挪用这个要领向ChangeToken塞入委托的。有一种情况是B但愿在塞入委托的同时附带一个状态东西,将来委托被执行时这个状态东西作为执行委托的参数

CancellationChangeToken是一个用的对照多的实现类,它包罗一个CancellationToken属性,这个属性是通过结构函数来初始化的(CancellationTokenSource、CancellationToken自行盘问相关资料),
简化的源码如下:

1 public class CancellationChangeToken : IChangeToken 2 { 3 public CancellationChangeToken(CancellationToken cancellationToken) 4 { 5 Token = cancellationToken; 6 } 7 8 public bool ActiveChangeCallbacks { get; private set; } = true; 9 10 public bool HasChanged => Token.IsCancellationRequested; 11 12 private CancellationToken Token { get; } 13 14 public IDisposable RegisterChangeCallback(Action<object> callback, object state) 15 { 16 return Token.Register(callback, state); 17 } 18 }

因为CancellationToken天然的已经现了IChangeToken,因此CancellationChangeToken只是对CancellationToken的包装。那为啥不直接让CancellationToken实现IChangeToken呢?我觉得是设计意图差别,CancellationToken设计时主要是考虑应用在打消异步操纵这件事上的,只是碰巧打消异步操纵与变动通知设计思路是相似的,所以才呈现CancellationChangeToken

其它的实现类没去研究过,但是只要你对这种设计思路理解了,碰到其它实现类应该看看就大白了

例子

下面我们使用CancellationChangeToken来完成上面的A、B类,A类状态变革时 通知到B类(其实就是执行B类忘ChangeToken中塞入的委托),完整源码如下:

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Console.OutputEncoding = Encoding.UTF8; 6 CancellationTokenSource cts = new CancellationTokenSource(); 7 CancellationChangeToken cct = new CancellationChangeToken(cts.Token); 8 var a = new A(cts); 9 var b = new B(cct); 10 Console.ReadKey(); 11 } 12 } 13 14 public class A 15 { 16 CancellationTokenSource _cts; 17 public A(CancellationTokenSource cts) 18 { 19 this._cts = cts; 20 Task.Run(() => 21 { 22 Task.Delay(2000).Wait(); 23 Console.WriteLine("模拟触发变动通知"); 24 _cts.Cancel(); 25 }); 26 } 27 } 28 public class B 29 { 30 public B(CancellationChangeToken cct) { 31 object testState = 1; 32 cct.RegisterChangeCallback(obj => { 33 //将来cct检测到变革时此委托会被执行 34 //obj是注册委托是通报进来的参数,就是这里的testState 35 Console.WriteLine($"状态变革了,状态值{obj}"); 36 }, testState); 37 } 38 }

上面只是演示IChangeToken的思路,asp.net core中源码的应用时凡是是在A中供给一个返回IChangeToken的要领

无限监控与ChangeToken.OnChange

上面的方法只能变换通知一次,下面可以永远监控

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30752.html