欢迎访问本站!

首页科技正文

2022世界杯预选赛赛程欧洲(www.9cx.net):.Net中异步义务的作废和监控

admin2021-09-0619

新2手机管理端网址

www.22223388.com)实时更新发布最新最快最有效的新2手机管理端网址,包括新2手机网址,新2备用网址,皇冠最新网址,新2足球网址,新2网址大全。

,

相关类型:

CancellationTokenSource 主要用来确立或作废令牌

CancellationToken 监听令牌状态,注册令牌作废事宜

OperationCanceledException 令牌被作废时抛出的异常,可以由监听者自主决议是否抛出异常



CancellationTokenSource

确立令牌:

CancellationTokenSource cts = new CancellationTokenSource()

CancellationToken token=cts.Token;

作废释放令牌:

cts.Cancel();


CancellationToken

监听令牌作废事宜:

token.Register(() => Console.WriteLine("令牌被作废"));

判断令牌是否作废

//返回一个bool,若是令牌被作废为true
token.IsCancellationRequested

//若是token被作废则抛出异常,内部实现实在就是判断IsCancellationRequested
token.ThrowIfCancellationRequested()=>{
	if(token.IsCancellationRequested){
		throw new OperationCanceledException();
	}
}


代码示例

下面模拟一个文件下载的义务,在未下载完成后下载义务被作废

 public void Run()
 {
     CancellationTokenSource cts = new CancellationTokenSource();

     Task.Run(() =>
              {
                  //守候两秒后作废,模拟的是用户自动作废下载义务
                  Thread.Sleep(2000);
                  cts.Cancel();
              });

     try
     {
         var size = DownloadFile(cts.Token);
         Console.WriteLine("文件巨细:" + size);
     }
     catch (OperationCanceledException)
     {
         Console.WriteLine("下载失败");
     }finally{
         cts.Dispose();
     }
     Thread.Sleep(2000);
 }


/// <summary>
/// 模拟下载文件,下载文件需要五秒
/// </summary>
/// <returns></returns>
public int DownloadFile(CancellationToken token)
{
    token.Register(() =>
                   {
                       System.Console.WriteLine("监听到作废事宜");
                   });

    Console.WriteLine("最先下载文件");
    for (int i = 0; i < 5; i++)
    {
        token.ThrowIfCancellationRequested();
        Console.WriteLine(i.ToString());
        Thread.Sleep(1000);
    }
    Console.WriteLine("文件下载完成");
    return 100;
}

输出效果:

最先下载文件
0
1
监听到作废事宜
下载失败

思索

为什么要将CancellationToken和CancellationTokenSource分为两个类呢,直接一个CancellationToken又可以作废又可以判断状态注册啥的不是更好,更利便?

实在每种类的设计和实现都可以有许多差其余战略,CTS和CT从这个两个类提供的为数不多的公然方式中就可以看出,CTS用来控制Token的天生和作废等生命周期状态,CT只能用来监听和判断,无法对Token的状态举行改变。

以是这种设计的目的就是关注点星散。限制了CT的功效,阻止Token在转达历程中被不能控的因素作废造成杂乱。



关联令牌

继续拿上面的示例来说,示例中实现了从外部控制文件下载功效的终止。

若是要给文件下载功效加一个超时时间的限制,此时可以增添一个控制超时时间的token,将外部传来的token和内部token 关联起来变为一个token

只需要将DownloadFile()函数做如下刷新即可

2022世界杯预选赛赛程欧洲www.9cx.net)实时更新比分2022世界杯预选赛赛程欧洲数据,2022世界杯预选赛赛程欧洲全程高清免费不卡顿,100%原生直播,2022世界杯预选赛赛程欧洲这里都有。给你一个完美的观赛体验。

public int DownloadFile(CancellationToken externalToken)
        {
            //通过组织函数设置TokenSource一秒之后挪用Cancel()函数
            var timeOutToken = new CancellationTokenSource(new TimeSpan(0, 0, 1)).Token;
            using (var linkToken = CancellationTokenSource.CreateLinkedTokenSource(externalToken, timeOutToken))
            {
                Console.WriteLine("最先下载文件");
                for (int i = 0; i < 5; i++)
                {
                    linkToken.Token.ThrowIfCancellationRequested();
                    Console.WriteLine(i.ToString());
                    Thread.Sleep(1000);
                }
                Console.WriteLine("文件下载完成");
                return 100;
            }
        }

此时岂论是externalToken作废,或是timeOutToken作废,都市触发linkToken的作废事宜



CancellationChangeToken

CancellationChangeToken主要用来监测目的转变,需配合ChangeToken使用。从功效场景来说,实在ChangeToken的功效和事宜似乎差不多,当监控的目的发生了转变,监听者去做一系列的事情。

然则事宜的话,监听者需要知道目的的存在,就是若是A要注册B的事宜,A是要依赖B的。

CancellationChangeToken是基于CancellationToken来实现的,可以做到依赖于Token而不直接依赖被监听的类

确立CancellationChangeToken:

new CancellationChangeToken(new CancellationTokenSource().Token)

监听Token更改

new CancellationChangeToken(cts.Token).RegisterChangeCallback(obj => Console.WriteLine("token 更改"), null);

CancellationChangeToken只是把CancellationToken包装了一层。RegisterChangeCallback最终也是监听的CancellationToken的IsCancellationRequested状态。

以是就有个问题,代码写到这里,并不能实现每次内部更改都触发回调事宜。

由于CT只会Cancel一次,对应的监听也会执行一次。无法实现多次监听

为了实现转变的连续监听,需要做两个操作

  • 让Token在Cancel之后重新初始化
  • 每次Cancel回调之后重新监听新的Token

先上代码,下面的代码实现了每次时间更改都市通知展示面板刷新时间的显示

public void Run()
{
    var bjDate = new BeijingDate();
    DisplayDate(bjDate.GetChangeToken, bjDate.GetDate);
    Thread.Sleep(50000);
}

public void DisplayDate(Func<IChangeToken> getChangeToken, Func<DateTime> getDate)
{
    ChangeToken.OnChange(getChangeToken, () => Console.WriteLine("当前时间:" + getDate()));
}

public class BeijingDate
{
    private CancellationTokenSource cts;
    private DateTime date;
    public BeijingDate()
    {
        cts = new CancellationTokenSource();
        var timer = new Timer(TimeChange, null, 0, 1000);
    }

    private void TimeChange(object state)
    {
        date = DateTime.Now;
        var old = cts;
        cts = new CancellationTokenSource();
        old.Cancel();
    }

    public DateTime GetDate() => date;
    public CancellationChangeToken GetChangeToken()
    {
        return new CancellationChangeToken(cts.Token);
    }
}

TimeChange()中修改了时间,重置了Token并将旧的Token作废

DisplayDate中用ChangeToken.OnChange获取对应的Token并监听

实现了DisplayData函数和BeijingDate这个类的解耦

ChangeToken.OnChange 这个函数吸收两个参数,一个是获取Token的委托,一个是Token作废事宜的响应委托。

每次在处置完Token的作废事宜后,他会重新挪用第一个委托获取Token,而此时我们已经天生了新的Token,最终实现了连续监控

网友评论