一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - .Net中異步任務的取消和監控的具體實現

.Net中異步任務的取消和監控的具體實現

2021-12-18 17:02藍夏 ASP.NET教程

本文主要介紹了.Net中異步任務的取消和監控的具體實現,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

相關類型:

  • CancellationTokenSource 主要用來創建或取消令牌
  • CancellationToken 監聽令牌狀態,注冊令牌取消事件
  • OperationCanceledException 令牌被取消時拋出的異常,可以由監聽者自主決定是否拋出異常

CancellationTokenSource

創建令牌:

?
1
2
3
CancellationTokenSource cts = new CancellationTokenSource()
 
CancellationToken token=cts.Token;

取消釋放令牌:

?
1
cts.Cancel();

CancellationToken

監聽令牌取消事件:

?
1
token.Register(() => Console.WriteLine("令牌被取消"));

判斷令牌是否取消

?
1
2
3
4
5
6
7
8
9
//返回一個bool,如果令牌被取消為true
token.IsCancellationRequested
 
//如果token被取消則拋出異常,內部實現其實就是判斷IsCancellationRequested
token.ThrowIfCancellationRequested()=>{
 if(token.IsCancellationRequested){
  throw new OperationCanceledException();
 }
}

代碼示例

下面模擬一個文件下載的任務,在未下載完成后下載任務被取消

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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()函數做如下改造即可

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

?
1
new CancellationChangeToken(new CancellationTokenSource().Token)

監聽Token變動

?
1
new CancellationChangeToken(cts.Token).RegisterChangeCallback(obj => Console.WriteLine("token 變動"), null);

CancellationChangeToken只是把CancellationToken包裝了一層。RegisterChangeCallback最終也是監聽的CancellationToken的IsCancellationRequested狀態。

所以就有個問題,代碼寫到這里,并不能實現每次內部變動都觸發回調事件。

因為CT只會Cancel一次,對應的監聽也會執行一次。無法實現多次監聽

為了實現變化的持續監聽,需要做兩個操作

  • 讓Token在Cancel之后重新初始化
  • 每次Cancel回調之后重新監聽新的Token

先上代碼,下面的代碼實現了每次時間變動都會通知展示面板刷新時間的顯示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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,最終實現了持續監控

到此這篇關于.Net中異步任務的取消和監控的文章就介紹到這了,更多相關.Net中異步任務的取消和監控內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/bluesummer/p/15219701.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 和岳m的小说| 农村妇女野战bbxxx | 国产中文在线 | 67194最新网址 | 免费网站看v片在线成人国产系列 | 亚洲免费黄色网 | 91香蕉视频在线观看 | 国语第一次处破女 | 亚洲系列在线 | 亚洲丰满模特裸做爰 | 国产高清不卡视频在线播放 | 91碰碰| 日产欧产va1| 亚洲国内精品久久 | 99这里都是精品 | 手机在线观看国产精选免费 | 国产精品视频2021 | 国产欧美二区三区 | 55夜色66夜亚州精品站 | 亚洲男人天堂 | 美女18隐私羞羞视频网站 | 情人梁家辉在线 | 被巨大黑人的翻白眼 | 男人的j进入女人的j免费 | kkkk4444在线看片| 午夜办公室在线观看高清电影 | 91禁漫| 百合女女师生play黄肉黄 | 91正在 播放 | 婷婷丁香色综合狠狠色 | 丰满大屁股美女一级毛片 | caoporn超碰最新地址进入 | 好大好深好舒服 | 精品久久免费视频 | 日韩中文在线 | 99久久香蕉国产线看观香 | 精品亚洲麻豆1区2区3区 | 1024免费观看完整版在线播放 | 午夜国产精品影院在线观看 | 丝袜护士强制脚足取精 | 国产精品亚洲精品观看不卡 |