c# Task任務(wù)的取消方式
Task任務(wù)的取消
c# 任務(wù)的取消,需要用到CancellationTokenSource類,CancellationToken結(jié)構(gòu)體。
注意:CancellationTokenSource是class類型,而CancellationToken是struct結(jié)構(gòu)體。
任務(wù)內(nèi)部"監(jiān)聽(tīng)"CancellationToken方法
任務(wù)的內(nèi)部在合適的時(shí)候不停地調(diào)用CancellationToken的ThrowIfCancellationRequested()方法,這個(gè)函數(shù)會(huì)拋出一個(gè)叫做OperationCanceledException的異常,它的實(shí)現(xiàn)(微軟開(kāi)源代碼)如下:
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
ThrowOperationCanceledException();
}下面的列子通過(guò)Task.Run產(chǎn)生了一個(gè)任務(wù)。Task任務(wù)的內(nèi)部正式通過(guò)拋出OperationCanceledException異常達(dá)到被取消的目的。而任務(wù)的外部則是通過(guò)調(diào)用CancellationTokenSource實(shí)例的Cancel()方法來(lái)觸發(fā)取消的動(dòng)作的。
下面的例子是一個(gè)取消Task任務(wù)的例子
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var tokenSource3 = new CancellationTokenSource();
var task = Task.Run(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
// Clean up here, then...
if(ct.IsCancellationRequested)
{
ct.ThrowIfCancellationRequested();
}
}
},tokenSource2.Token); // Pass same token to Task.Run.
Thread.Sleep(5000);
tokenSource2.Cancel();
// Just continue on this thread, or await with try-catch:
try
{
await task;
}
catch (OperationCanceledException e)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
bool eqs = e.CancellationToken.Equals(tokenSource3.Token);
System.Console.WriteLine($"Equals' result: {eqs}.");
System.Console.WriteLine($"Task's status: {task.Status}");
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
}
finally
{
tokenSource2.Dispose();
}
Console.ReadKey();
}
}
/*
The operation was canceled.
OperationCanceledException thrown with message: The operation was canceled.
Equals' result: False.
Task's status: Canceled
*/這個(gè)例子中我們?cè)赥ask的外部創(chuàng)建了2個(gè)CancellationTokenSource實(shí)例,因?yàn)镃ancellationTokenSource類包含一個(gè)CancellationToken類的屬性Token,這也就意味著例子當(dāng)中包含了兩個(gè)CancellationToken實(shí)例。
ThrowIfCancellationRequested()方法會(huì)把調(diào)用它的CancellationToken實(shí)例也作為參數(shù)一起攜帶拋出。
因此catch塊參數(shù)e中包含的是tokenSource2.Token,因此它與tokenSource3.Token進(jìn)行相等比較輸出一定是false。
又因?yàn)門(mén)ask.Run()方法中傳入的第二個(gè)參數(shù)也是tokenSource2.Token,Task核心框架內(nèi)部會(huì)比較OperationCanceledException異常中攜帶的CancellationToken實(shí)例和Task.Run()方法中傳入的CancellationToken實(shí)例,如果兩者是一樣的,則Task的status狀態(tài)設(shè)為Canceled,表示成功取消;如果兩者不一樣,Task任務(wù)仍然會(huì)退出,但是Task的status狀態(tài)設(shè)為Faulted,表示出錯(cuò)。
如果將第29行改為:
},tokenSource3.Token); // Pass same token to Task.Run.
則,結(jié)果輸出如下:
OperationCanceledException thrown with message: The operation was canceled.
Equals' result: False.
Task's status: Faulted
看起來(lái),Task任務(wù)也被取消了,但是實(shí)際上是由于出錯(cuò)而退出。因此,Task.Run的第二個(gè)參數(shù)可以用來(lái)確保內(nèi)部實(shí)際引發(fā)取消異常的CancellationToken實(shí)例和Task.Run傳入的CancellationToken實(shí)例要一致才能成功取消,否則框架會(huì)誤認(rèn)為你是誤操作而導(dǎo)致退出的。因此,Task.Run的CancellationToken參數(shù)是為了更加安全。
如果將29行改為不帶CancellationToken參數(shù)的重載函數(shù),那么返回的也是一樣的Faulted結(jié)果。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#連續(xù)任務(wù)Task.ContinueWith方法
這篇文章介紹了C#中的連續(xù)任務(wù)Task.ContinueWith方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-04-04
使用C# Winform應(yīng)用程序獲取網(wǎng)頁(yè)源文件的解決方法
本篇文章是對(duì)使用C# Winform應(yīng)用程序獲取網(wǎng)頁(yè)源文件的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#模擬實(shí)現(xiàn)抽獎(jiǎng)小程序的示例代碼
這篇文章主要介紹了通過(guò)C#模擬實(shí)現(xiàn)一個(gè)簡(jiǎn)單的抽獎(jiǎng)小程序,文中的示例代碼講解詳細(xì),對(duì)我們了解C#有一定的幫助,需要的可以參考一下2021-12-12
C# 正則表達(dá)式常用的符號(hào)和模式解析(最新推薦)
這篇文章主要介紹了C# 正則表達(dá)式常用的符號(hào)和模式解析,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
C#使用Newtonsoft.Json庫(kù)實(shí)現(xiàn)JSON數(shù)據(jù)中某個(gè)字段值的提取功能
在C#中,可以使用Newtonsoft.Json庫(kù)(也稱為Json.NET)來(lái)處理JSON數(shù)據(jù),下面將通過(guò)幾個(gè)示例來(lái)展示如何從JSON格式的文本中提取某個(gè)字段的值,并將其存儲(chǔ)到字符串、列表或其他泛型集合中,需要的朋友可以參考下2025-03-03

