1. ホーム
  2. c#

[解決済み] CancellationTokenSourceを破棄するタイミングは?

2022-04-22 07:05:45

質問

クラス CancellationTokenSource は使い捨てです。Reflector で見てみると KernelEvent という、(おそらく)管理されていないリソースがあります。 ということは CancellationTokenSource はファイナライザを持たないので、もし廃棄しなければGCはそれを行いません。

一方、MSDNの記事に掲載されているサンプルを見てみると マネージド・スレッドにおけるキャンセル トークンを破棄するコードスニペットは1つだけです。

コードで廃棄する適切な方法は何ですか?

  1. 並列タスクを開始するコードを using を待っていなければなりません。そして、待たされない場合にのみキャンセルを行うことは理にかなっています。
  2. もちろん ContinueWith を使ってタスクに Dispose を呼び出すのですが、その方法で良いのでしょうか?
  3. キャンセル可能なPLINQクエリについてはどうでしょうか。これは同期を戻さず、最後に何かを行うだけです。例えば .ForAll(x => Console.Write(x)) ?
  4. 再利用可能ですか?同じトークンを複数の呼び出しに使用し、ホスト コンポーネント(たとえばUIコントロール)と共に破棄することができますか?

のようなものがないため Reset をクリーンアップするメソッド IsCancelRequestedToken フィールドは再利用できないので、タスク(またはPLINQクエリ)を開始するたびに新しいものを作成しなければならないと思います。本当でしょうか?もしそうなら、私の質問は、次のような対処をするための正しい、そして推奨される戦略とは何かということです。 Dispose を使用した場合、その多くの CancellationTokenSource のインスタンスですか?

解決方法は?

でDisposeを呼び出すことが本当に必要なのか、という話。 CancellationTokenSource ... 私のプロジェクトでメモリリークが発生し、その結果 CancellationTokenSource が問題でした。

私のプロジェクトには、常にデータベースを読み込み、さまざまなタスクを開始するサービスがあります。私はリンクされたキャンセルトークンをワーカーに渡していたので、ワーカーがデータ処理を終えた後でもキャンセルトークンが破棄されず、メモリリークの原因となりました。

MSDN マネージド・スレッドにおけるキャンセル が明確に述べています。

を呼び出す必要があることに注意してください。 Dispose をリンクされたトークン・ソース上で使用することができます。より完全な例としては How to: 複数のキャンセル要求をリッスンする .

を使いました。 ContinueWith を実装しました。