如何在C#中使用 CancellationToken 處理異步任務(wù)
在 .NET Core 中使用異步編程已經(jīng)很普遍了, 你在項(xiàng)目中隨處可見(jiàn) async 和 await,它簡(jiǎn)化了異步操作,允許開(kāi)發(fā)人員,使用同步的方式編寫(xiě)異步代碼,你會(huì)發(fā)現(xiàn)在大部分的異步方法中,都提供了CancellationToken參數(shù),本文主要介紹下 CancellationTokenSource 和 CancellationToken在異步任務(wù)中的使用。
手動(dòng)取消任務(wù)
創(chuàng)建一個(gè) CancellationTokenSource,然后調(diào)用異步方法時(shí),傳入 CancellationToken,它是一個(gè)輕量級(jí)對(duì)象,可以通知請(qǐng)求是否已取消,我們可以手動(dòng)調(diào)用 cts.Cancel() 來(lái)取消任務(wù),為了方面演示,這里我有用到局部方法。
static async Task Main(string[] args)
{
async Task Execute(CancellationToken token)
{
await Task.Delay(3000, token);
Console.WriteLine("Executed");
}
CancellationTokenSource cts = new CancellationTokenSource();
_ = Execute(cts.Token);
// 手動(dòng)取消任務(wù)
cts.Cancel();
Console.ReadKey();
}
定時(shí)取消任務(wù)
創(chuàng)建 CancellationTokenSource 的時(shí)候,可以傳入時(shí)間(毫秒或者Timespan), 通過(guò)它我們可以在等待一段時(shí)間后,自動(dòng)取消任務(wù)。
CancellationTokenSource cts = new CancellationTokenSource(1000); _ = Execute(cts.Token); Console.ReadKey();
我們也可以調(diào)用 cts.CancelAfter(1000), 它會(huì)在1s后取消任務(wù)。
cts.CancelAfter(1000);
CancellationToken 注冊(cè)回調(diào)
我們可以調(diào)用 Register()方法,注冊(cè)Token取消的回調(diào),參數(shù)需要傳入 Action 委托。
CancellationTokenSource cts = new CancellationTokenSource(1000);
cts.Token.Register(() => Console.WriteLine("任務(wù)已取消!"));
// 開(kāi)始異步任務(wù)
_ = Execute(cts.Token);
Console.ReadKey();
Register() 注冊(cè)回調(diào)后,返回一個(gè) CancellationTokenRegistration 對(duì)象,同樣的,你可以在回調(diào)函數(shù)執(zhí)行前,移除注冊(cè)回調(diào),就像這樣:
cts.Token.Register(() => Console.WriteLine("任務(wù)已取消!")).Unregister();
在 HttpClient 中使用
同樣,你可以在 HttpClient 中使用傳入 CancellationToken (或者使用HttpClient的Timeout屬性),超時(shí)后,它會(huì)拋出一個(gè) TaskCanceledException 的異常:
CancellationTokenSource cts = new CancellationTokenSource(10);
_ = await new HttpClient().GetAsync("https://www.youtube.com/",cts.Token);
Console.ReadKey();
在 WebAPI中使用
我創(chuàng)建了一個(gè) WebAPI 項(xiàng)目,其中的控制器代碼如下,等待了5s,然后進(jìn)行輸出信息。
[HttpGet]
public async Task<IActionResult> Index()
{
await Task.Delay(5000);
Console.WriteLine("Executed");
return Ok();
}
啟動(dòng)項(xiàng)目后,我們?cè)跒g覽器頁(yè)面上訪問(wèn)接口,在第一次訪問(wèn)接口等待響應(yīng)時(shí),我刷新一次了頁(yè)面,現(xiàn)在程序的輸出信息如下:

說(shuō)明前臺(tái)頁(yè)面刷新后,后臺(tái)并沒(méi)有做取消操作,執(zhí)行了兩次!
我們可以把程序改成這樣,傳入 CancellationToken
[HttpGet]
public async Task<IActionResult> Index(CancellationToken token)
{
await Task.Delay(5000,token);
Console.WriteLine("Executed");
return Ok();
}
現(xiàn)在在瀏覽器訪問(wèn)頁(yè)面,同樣的,第一次還未返回是,我們刷新一次頁(yè)面,程序輸出如下:

只有一次輸出,第一次請(qǐng)求拋出了一次 TaskCanceledException 異常,沒(méi)有繼續(xù)執(zhí)行后邊的邏輯,當(dāng)然你可以捕獲這個(gè)異常,返回更友好的提示!
以上就是如何在C#中使用 CancellationToken 處理異步任務(wù)的詳細(xì)內(nèi)容,更多關(guān)于C# 用CancellationToken 處理異步任務(wù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#云存儲(chǔ)服務(wù)的訪問(wèn)控制與權(quán)限管理的全面指南
在云計(jì)算時(shí)代,云存儲(chǔ)服務(wù)的訪問(wèn)控制與權(quán)限管理是保障數(shù)據(jù)安全的基石,無(wú)論是AWS S3、Azure Blob Storage還是阿里云OSS,權(quán)限配置不當(dāng)可能導(dǎo)致數(shù)據(jù)泄露、未授權(quán)訪問(wèn)甚至惡意攻擊,本文給大家介紹了C#云存儲(chǔ)服務(wù)的訪問(wèn)控制與權(quán)限管理的全面指南,需要的朋友可以參考下2025-08-08
WinForm實(shí)現(xiàn)關(guān)閉按鈕不可用或隱藏的方法
這篇文章主要介紹了WinForm實(shí)現(xiàn)關(guān)閉按鈕不可用或隱藏的方法,很實(shí)用的功能,需要的朋友可以參考下2014-08-08
C#微信開(kāi)發(fā)之微信公眾號(hào)標(biāo)簽管理功能
這篇文章主要介紹了C#微信開(kāi)發(fā)之微信公眾號(hào)標(biāo)簽管理功能 的相關(guān)資料,需要的朋友可以參考下2016-05-05
C#基于SQLiteHelper類(lèi)似SqlHelper類(lèi)實(shí)現(xiàn)存取Sqlite數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了C#基于SQLiteHelper類(lèi)似SqlHelper類(lèi)實(shí)現(xiàn)存取Sqlite數(shù)據(jù)庫(kù)的方法,涉及C#操作SQLite數(shù)據(jù)庫(kù)的相關(guān)技巧,需要的朋友可以參考下2015-06-06
C#使用Spire.Doc解決Word轉(zhuǎn)PDF亂碼/錯(cuò)位的方案
在日常開(kāi)發(fā)中,Word轉(zhuǎn)PDF的功能需求十分常見(jiàn),但實(shí)現(xiàn)過(guò)程中往往會(huì)遇到一些棘手的挑戰(zhàn),無(wú)論是系統(tǒng)自動(dòng)生成的報(bào)告,還是用戶上傳的文檔,轉(zhuǎn)換后出現(xiàn)亂碼、排版錯(cuò)位等問(wèn)題,所以本文給大家介紹了如何使用Spire.Doc完美解決Word轉(zhuǎn)PDF亂碼/錯(cuò)位問(wèn)題,需要的朋友可以參考下2025-09-09

