非同期タスクキャンセルと監視のネット実装
関連する種類
- CancellationTokenSourceは、主にトークンの作成またはキャンセルに使用される
- CancellationTokenはトークンの状態をリッスンし、トークンのキャンセル・イベントを登録する
- OperationCanceledException トークンがキャンセルされたときにスローされる例外で、リスナーが任意にスローできる。
CancellationTokenSource
トークンを作成します。
CancellationTokenSource cts = new CancellationTokenSource()
CancellationToken token=cts;
解約解除トークンです。
cts.Cancel();
キャンセルトークン
トークンキャンセルイベントをリスニングします。
token.Register(() => Console.WriteLine("token cancelled"));
トークンがキャンセルされたかどうかの判定
//returns a bool, true if the token was cancelled
token.IsCancellationRequested
//Throw an exception if the token is cancelled, the internal implementation actually determines IsCancellationRequested
token.ThrowIfCancellationRequested()=>{
if(token.IsCancellationRequested){
throw new OperationCanceledException();
}
}
コード例
以下は、ダウンロードが完了する前にキャンセルされたファイルダウンロードのタスクをシミュレートしたものです。
public void Run()
{
CancellationTokenSource cts = new CancellationTokenSource();
Task.Run(() =>
{
// wait two seconds and then cancel, simulating a user-initiated cancellation of the download task
Thread.Sleep(2000);
cts.Cancel();
Try)
Try
{
var size = DownloadFile(cts.Token);
Console.WriteLine("File size: " + size);
}
catch (OperationCanceledException)
{
Console.WriteLine("Download failed");
}finally{
cts.Dispose();
}
Thread.Sleep(2000);
}
/// <summary>
/// Simulate downloading a file, it takes five seconds to download the file
/// </summary>
//// <returns></returns>
public int DownloadFile(CancellationToken token)
{
token.Register(() =>
{
System.Console.WriteLine("Listening to cancellation event");
});
Console.WriteLine("Started downloading file");
for (int i = 0; i < 5; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine(i.ToString());
Thread.Sleep(1000);
Sleep(1000); }
Console.WriteLine("File download complete");
return 100;
}
出力結果です。
ファイルのダウンロードを開始
0
1
キャンセルイベントのリスニング
ダウンロードに失敗しました
振り返り
なぜ、CancelationToken と CancelationTokenSource を2つのクラスに分ける必要があるのでしょうか。キャンセルとステータス登録の判定もできるCancelationTokenを直接用意したほうが便利でいいのでは?
実際には、各クラスの設計と実装は、多くの異なる戦略を持つことができます、CTSとCTの2つのクラスが提供するいくつかのパブリックメソッドから見ることができる、CTSはトークンのライフサイクル状態の生成とキャンセルを制御するために使用され、CTのみ聞いて判断に使用できる、トークンの状態を変更することはできません。
つまり、この設計の目的は関心事の分離です。CTの機能を制限し、配信プロセスにおいて制御不能な要因でTokenがキャンセルされることによる混乱を回避するためです。
関連するトークン
上記の例に引き続き、外部制御ファイルからのダウンロード機能の終了を実装する例です。
ファイルのダウンロード機能にタイムアウトの制限を加えたい場合は、外部トークンと内部トークンを関連付けてトークンにすることで、タイムアウトを制御することができます
DownloadFile()関数に以下の変更を加えるだけです。
public int DownloadFile(CancellationToken externalToken)
{
//Cancel() function is called after one second of setting the TokenSource through the constructor
var timeOutToken = new CancellationTokenSource(new TimeSpan(0, 0, 1)).Token;
using (var linkToken = CancellationTokenSource.CreateLinkedTokenSource(externalToken, timeOutToken))
{
Console.WriteLine("Start downloading file");
for (int i = 0; i < 5; i++)
{
linkToken.Token.ThrowIfCancellationRequested();
Console.WriteLine(i.ToString());
Thread.Sleep(1000);
Sleep(1000); }
Console.WriteLine("File download complete");
return 100;
}
}
この時点で、externalTokenのキャンセルまたはtimeOutTokenのキャンセルのどちらかが、linkTokenのキャンセルイベントをトリガーします。
キャンセルチェンジャートークン
CancellationChangeToken は、主にターゲットの変更を監視するために使用され、ChangeToken と一緒に使用されます。機能的なシナリオとしては、監視対象が変更されると、リスナーが一連の処理を行うという点で、ChangeToken は実際にはイベントと同様に機能するように思われます。
しかし、イベントの場合、リスナーはターゲットの存在を知っている必要があります。つまり、AがBのイベントに登録したい場合、AはBに依存していることになるのです。
CancellationChangeTokenは、CancellationTokenをベースにしており、リスニングされるクラスに直接依存せず、トークンに依存することで実現することができます
CancellationChangeTokenを作成するには。
new CancellationChangeToken(new CancellationTokenSource().Token)
トークンの変更をリスニングする
new CancellationChangeToken(cts.Token).RegisterChangeCallback(obj => Console.WriteLine("token change"), null);
CancellationChangeTokenは、CancellationTokenをレイヤーで包むだけです。registerChangeCallbackは、CancellationTokenのIsCancellationRequested状態をリスニングして終了します。
つまり、ここに書かれているコードでは、内部変更のたびにコールバック・イベントをトリガーすることができないのです。
なぜなら、CTは一度だけCancelし、対応するリスナーは一度だけ実行されるからです。複数のリスナーはできません
継続的に変更をリッスンするためには、次の2つのアクションを行う必要があります。
- Cancel後にTokenを再初期化させる
- 各 Cancel コールバックの後に新しい Token を再リスト化する。
まずは以下のコードから。表示パネルに時刻が変わるたびに更新するよう通知する表示を実装しています。
public void Run()
{
var bjDate = new BeijingDate();
DisplayDate(bjDate.GetChangeToken, bjDate.GetDate);
Thread.Sleep(50000);
}
public void DisplayDate(Func<IChangeToken> getChangeToken, Func<DateTime> getDate)
{
ChangeToken.OnChange(getChangeToken, () => Console.WriteLine("Current Time: " + getDate())));
}
public class BeijingDate
{
private CancellationTokenSource cts;
private DateTime date;
public BeijingDate()
{
cts = new CancellationTokenSource();
var timer = new Timer(TimeChange, null, 0, 1000);
}
private void TimeChange(object state)
{
date = DateTime;
var old = cts;
cts = new CancellationTokenSource();
old.Cancel();
}
public DateTime GetDate() => date;
public CancellationChangeToken GetChangeToken()
{
return new CancellationChangeToken(cts.Token);
}
}
TimeChange()で時間を変更し、Tokenをリセットして古いものをキャンセルした
ChangeToken.OnChangeでDisplayDateに対応するTokenを取得し、それをリッスンする。
DisplayData関数をBeijingDateクラスからデカップリングする。
ChangeToken.OnChange この関数は、トークンを取得するデリゲートと、トークンのキャンセル・イベントに応答するデリゲートの 2 つのパラメータを取ります。
Tokenキャンセルイベントが処理されるたびに、最初のデリゲートを再コールしてTokenを取得し、その時までに新しいTokenを生成し、最終的に継続的な監視を可能にします。
ネットでは、スクリプトハウスの過去の記事を検索するか、以下の関連記事を引き続き閲覧して、スクリプトハウスからのサポートをご確認ください!
関連
-
.netcoreプロジェクトでIStartupFilterを使用するためのチュートリアル
-
pythonでpillowをインストールする3つの方法
-
.NET 6:.NETのロギングコンポーネントlog4netを使用する。
-
NETガベージコレクション GC診断ツール dotnet-gcmon 使用方法
-
ASP.NET CoreでURLを設定する5つの方法
-
30分でわかるコング経由の.NETゲートウェイ
-
net core downlink tracking skywalking インストールと使いやすいチュートリアル
-
swagger uiをasp.net coreに統合する原理
-
認証プロセスの記録にjwtを使用したネット
-
再起動を伴わないNET5の設定変更は自動的に反映される
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
.NET複数データベース一括データ挿入、更新(SqlServer、MySql、PgSql、Oracleをサポートします。)
-
NET6新機能 新構造体の最適化
-
ネットのメモリ管理に関する5つの基本
-
.NET開発サーバー アプリケーション管理ツール
-
ASP.NET Core ディペンデンシーインジェクションの詳細
-
ASP.NET学習でよくあるエラーのまとめ
-
ASP.NETでWeb.configからログインする際の正しいアカウントパスワードを確認する
-
NET 6 の今後の新機能 暗黙の名前空間参照
-
asp.net core3.1 cookieとjwtのハイブリッド認証による多様な認証ソリューションの実現
-
名前 'xxx' が現在のコンテキストに存在しない エラー解決方法の1つ