ニートが学ぶ非同期処理 スレッド処理のキャンセル

はいどーもおはようございますニートです。
本日はスレッド処理のキャンセルをおこないたいと思います。

Thread.Abort

たぶん超シンプルなのはThreadを生成して、Thread.Abortすることだと思います。
ただあんまり推奨してる感じの記事がないですし、そもそも生でThreadを扱うの自体勧めてる記事が皆無に近いです。
とりあえずThread.Abortできるよということだけ覚えておけば十分でしょうかね。

キャンセルトークン

こちらが本記事のメインです。
キャンセルトークンを用いると、メインスレッドから(別にメインスレッドに限りませんが)別スレッドに「おいスレッドちゃん! 今ちょっと具合が悪いからその処理中止してくれ!」とお願いすることができるようになります。
とりあえずコードを書いてみます。

コンソールログにものすごい勢いで数字が羅列されていきます。
途中で何かキーを押すと停止するのですが、即座に停止されるわけではなく、

ここまで来ないと停止しません。
つまりjの値は常に4999まで計算されます。

なぜ即座にスレッドを停止させず、わざわざ「キャンセルの要求」を出しているのかと言えば、例えば「別スレッドで実行中の処理を停止してほしいけど、きりのいいところまで実行してくれないとエラーが発生してしまう場合」などに役立つからです。

単に停止したいだけなら

先ほどの例ではbreakでループを脱出して処理を終わらせていましたが、混み合った処理でかつ、いつでも即座に停止していいなら、ThrowIfCancellationRequestedメソッドを使うのがよさそうです。
例えば以下のような感じ。

これでCancel要求が通知されたとき、OperationCanceledExceptionがスローされてスレッドが停止します。
もちろんtry-catchも可能です。
今回はしていませんが、別スレッドで実行中の処理をawaitして、OperationCanceledExceptionがスローされたとき(キャンセルされたとき)に「中断されたよ処理」を実行することなんかもできそうです。

CancellationTokenSourceとCancellationToken

CancellationTokenSourceからCancellationTokenを取得するのが一般的なようなのですが、この二つが分けられている理由はよくわかりませんでしたw
たぶん設計上の理由(SRPに従ってるとか)と、スレッドを中断させる部分で何か分けといたほうがお得なんでしょうね。

終わりに

キャンセルトークンって一体なんだってばよ!?
と疑問に思っていたのですが、勉強してみたら意外とシンプルでした。
苦手意識はいけませんね。

ほなそんな感じでまた。

フォローする