偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Dotnet線程取消的深度進(jìn)階

開(kāi)發(fā) 架構(gòu)
在 Dotnet 里,給出了一個(gè)東西,叫取消令牌 ( Cancellation Tokens )。這個(gè)令牌,就是請(qǐng)求取消的載體。

取消的概念

通常我們最熟悉的,是一個(gè)方法的中止。中止是完全的。一個(gè)方法中止了,則這個(gè)方法不再往下執(zhí)行,方法中前面已經(jīng)完成的部分會(huì)被拋棄,并返回一個(gè)設(shè)定的結(jié)果。

取消則不同。

通常,取消是由其它代碼發(fā)出的命令,也就是說(shuō),是由一些代碼去請(qǐng)求取消,另一部分代碼的響應(yīng)取消。而且,實(shí)際發(fā)生的情況,是請(qǐng)求代碼只是通知響應(yīng)代碼,希望它能停止執(zhí)行;響應(yīng)代碼會(huì)按照自己設(shè)定的方式對(duì)取消請(qǐng)求做出響應(yīng),有可能立即停止任務(wù),也有可能繼續(xù)運(yùn)行下去,直到一個(gè)可以停止的點(diǎn),甚至可能完全忽略這個(gè)取消請(qǐng)求。

概念清楚了,怎么做?

取消令牌

既然是一方請(qǐng)求,另一方響應(yīng),那對(duì)于響應(yīng)代碼來(lái)說(shuō),重要的是能夠知道并響應(yīng)取消請(qǐng)求。

在 Dotnet 里,給出了一個(gè)東西,叫取消令牌 ( Cancellation Tokens )。這個(gè)令牌,就是請(qǐng)求取消的載體。

請(qǐng)求代碼發(fā)起取消時(shí),實(shí)際是發(fā)起了一個(gè)對(duì)「取消令牌」的取消操作,然后,響應(yīng)代碼將對(duì)這個(gè)被取消的令牌做出正確反應(yīng)。

如果看到這兒有點(diǎn)混亂的話,看一下示例代碼:

async Task SomethingAsync(int data, CancellationToken cancellationToken)
{
var result = await FirstStepAsync(data, cancellationToken);
await SecondStepAsync(intermediateValue, cancellationToken);
}

響應(yīng)代碼基本都是這個(gè)樣子。這里面,CancellationToken 就是上面說(shuō)的取消令牌。

CancellationToken 可以在任何地方被設(shè)置為取消:用戶(hù)按下取消按鈕,或客戶(hù)端斷開(kāi)連接,超時(shí),等等。重要的是,當(dāng)它被設(shè)置為取消時(shí),就表示響應(yīng)代碼需要處理取消了。

注意:一個(gè) CancellationToken 只能被取消一次。一旦它被取消,就會(huì)永遠(yuǎn)保持取消狀態(tài)。

帶有取消令牌的方法定義

上面的示例,就是一個(gè)典型的帶有取消令牌的方法定義。

按照微軟的習(xí)慣,帶有 CancellationToken 的方法有以下約定:

  • CancellationToken 通常是最后一個(gè)參數(shù)
  • 方法通常會(huì)提供一個(gè)重載,或默認(rèn)參數(shù)值,以便調(diào)用者可以不提供取消令牌而直接調(diào)用

當(dāng)然,這是一個(gè)非強(qiáng)制的約定。如果你不介意別人看著別扭,可以不管這個(gè)約定。

看幾個(gè)例子:

Task SomethingAsync(int data) => SomethingAsync(data, CancellationToken.None);

async Task SomethingAsync(int data, CancellationToken cancellationToken)
{
...
}

async Task SomethingAsync(int data, CancellationToken cancellationToken = default)
{
...
}

在這里,CancellationToken 代表任何類(lèi)型或任何原因的取消。

通過(guò) CancellationToken 參數(shù),方法聲明了自己可以響應(yīng)取消。而實(shí)際上,這只是個(gè)聲明。代碼中,CancellationToken 可能會(huì)被忽略。因此,有這個(gè)聲明僅僅表示方法可能支持取消,而不是一定支持。

方法對(duì)取消的響應(yīng)

上面說(shuō)到了,響應(yīng)代碼可以響應(yīng)取消,也可以不取消。

而即使響應(yīng)代碼真的去響應(yīng)取消,通常也會(huì)有不同的情況。

通常來(lái)說(shuō),如果取消請(qǐng)求到達(dá)時(shí),響應(yīng)方法實(shí)際取消了一些工作,會(huì)拋出 OperationCanceledException 來(lái)通知調(diào)用程序;而如果取消被忽略,或者取消請(qǐng)求來(lái)的太晚而任務(wù)已經(jīng)完成,那響應(yīng)方法會(huì)正常返回,而且不拋出 OperationCanceledException 異常。這個(gè)在微軟的基礎(chǔ)類(lèi)庫(kù)(BCL)中,體現(xiàn)得很明顯。

大多數(shù)情況下,異常會(huì)被逐層傳出。再看一下上面的例子:

async Task SomethingAsync(int data, CancellationToken cancellationToken)
{
var result = await FirstStepAsync(data, cancellationToken);
await SecondStepAsync(intermediateValue, cancellationToken);
}

如果 FirstStepAsync 或 SecondStepAsync 拋出 OperationCanceledException,那這個(gè)異常也會(huì)從 SomethingAsync 中傳出給調(diào)用者。

這里要強(qiáng)調(diào)一下:看過(guò)很多代碼,在請(qǐng)求取消時(shí)會(huì)不拋出異常而直接返回。不要這樣做。調(diào)用者不知道這個(gè)取消是被接受,還是被忽略,會(huì)出大問(wèn)題的。

一個(gè)常見(jiàn)的錯(cuò)誤用法

在代碼 Review 時(shí),見(jiàn)過(guò)好幾次這樣的情況:

async Task SomethingAsync(CancellationToken cancellationToken)
{
var test = await Task.Run(() =>
{
...
}, cancellationToken);
...
}
// 注意,這個(gè)例子的寫(xiě)法是錯(cuò)的。

這個(gè)有必要專(zhuān)門(mén)拿出來(lái)說(shuō)一下。

很多人把委托和 CancellationToken 傳遞給 Task,期望在令牌取消時(shí)取消委托。注意,這個(gè)理解是錯(cuò)的。

Task.Run 是對(duì)線程池的委托調(diào)度,是一個(gè)立即完成的瞬時(shí)動(dòng)作。CancellationToken 在這兒的作用是取消調(diào)度這個(gè)動(dòng)作,而這個(gè)動(dòng)作是立即完成的,換句說(shuō)說(shuō),一旦走到這一行,調(diào)度操作會(huì)立即完成,這個(gè)取消令牌也就沒(méi)有用了,會(huì)被忽略。

所以,這種情況不需要用 CancellationToken,要寫(xiě)成下面的方式:

async Task SomethingAsync(CancellationToken cancellationToken)
{
var test = await Task.Run(( cancellationToken ) =>
{
...
});
...
}

寫(xiě)成這樣,才是正確的表達(dá),表達(dá)委托本身需要響應(yīng)令牌。

這是一個(gè)容易搞錯(cuò)的知識(shí)點(diǎn),記一下。

責(zé)任編輯:武曉燕 來(lái)源: 老王Plus
相關(guān)推薦

2021-12-29 07:44:50

Dotnet 代碼系統(tǒng)

2021-01-20 08:16:06

異步Dotnet Core多路徑

2021-10-27 09:59:35

存儲(chǔ)

2024-11-05 16:58:21

RabbitMQ訂單超時(shí)取消延遲隊(duì)列

2024-10-16 09:29:30

RabbitMQ延遲隊(duì)列

2021-03-03 08:13:57

模式垃圾回收

2021-09-11 07:32:15

Java線程線程池

2010-02-24 11:19:00

Python主線程

2021-03-10 07:20:44

數(shù)據(jù)定位匹配

2021-02-03 08:12:23

函數(shù)委托Dotnet

2021-06-02 08:07:59

LinuxService應(yīng)用

2021-05-26 11:30:24

Java線程池代碼

2022-09-29 09:35:56

線程池

2023-12-11 18:18:24

Python編程線程

2025-05-06 09:12:46

2011-04-20 17:15:21

并行計(jì)算

2011-04-21 09:13:14

并行計(jì)算

2021-07-07 08:01:51

命令行Dotnet Core控制臺(tái)

2021-03-17 08:12:03

架構(gòu)Dotnet洋蔥

2021-09-06 10:22:47

匿名對(duì)象編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)