在 .Net Core 世界中,非同步執行變成最基本的內容,甚至現在大部分系統設計理念皆是如此,若你對多執行序稍有了解,應該能理解放出去的 task 是很難掌控跑去哪的。
這次要介紹的是 CancellationToken
與 CancellationTokenSource
。
CancellationToken
首先來看這個物件的 Property
- CanBeCanceled: 此 token 是否可以被取消執行
- CanllationRequested: 此 token 是否被請求取消
- None: 直接使用空的 token,無法被取消或者請求取消
- WaitHandle: 阻塞當前執行緒直到收到取消請求,再繼續執行
在使用各種建構方式,其屬性分別是甚麼內容
1 | var token = new CancellationToken(); |
先前常見的無限執行方法:
1 | public static void InfiniteLoop() |
現在也建議採用正規作法,透過 CancellationToken
來傳遞是否取消執行的訊息
1 | public static void InfiniteLoop(CancellationToken token) |
透過這個物件的屬性我們能夠操控當前任務(task)是否需要取消,不過我們一般會與他的實例化的物件 CancellationTokenSource
一併使用,而 CancellationToken
僅負責當作參數傳遞。
CancellationTokenSource
用來實例化(instantiate) CancellationToken 的物件,簡單來說就是 Token 負責夾帶訊息,而 Source 負責指揮 Token 如何處理。
建構子
- CancellationTokenSource(int32): 過了 ms 後,自動執行取消
- CancellationTokenSource(timespan): 過了設定的 timespan 後,自動執行取消
屬性
- IsCancellationRequested: 如同 toekn 的屬性,取消是否被請求
- Token: 即 CancellationToken
方法
方法很多,舉幾個常使用的
- Cancel(): 執行取消請求
- CancelAfter(int32): 於 ms 後,執行取消請求
- Dispose: CancellationTokenSource 執行取消後,用於解構的方法
範例
上面介紹了無限迴圈的取消工作方法,這邊改用 Token 自帶的 ThrowIfCancellationRequested
方法取消
1 | public static async Task DemoCancelMethod() |
總結一下,其實這個概念很簡單。
- 非同步的方法都要帶入 token,使得工作得以取消,否則在啟動關閉服務時都會遇到噴錯的情形
- 也要知道呼叫 Cancel 的觸發點放在哪個位置比較好。
- 如果還需要處理 cancel 的 exception,可以在 catch 中使用
OperationCanceledException
來捕捉,並執行你要的處置。 While (true)
不是不行,只是程式很容易寫出邏輯 bug,導致永遠出不來。
Reference: