CancellationTokenRegistration.Unregister()
このパターンは、が自動的に呼び出されるようにする便利な方法です。これは、Stephen Toub のParallel Programming with .NETブログ投稿 (たとえば、こちら) でよく使用されます。
IDisposable を必ず Dispose する必要があると思いますが、なぜ IDisposable を実装しているのでしょうか? どのリソースを解放する必要がありますか? それが持っている唯一の方法は平等です。
IMO、これに対する最良の答えは、Microsoft の Mike Liddell による.NET 4 Cancellation Frameworkの投稿にあります。
コールバックが に登録されると、コールバックがまったく同じセキュリティ コンテキストで実行されるようCancellationToken
に、現在のスレッドがキャプチャされます。ExecutionContext
現在のスレッドの同期コンテキストのキャプチャはオプションであり、必要に応じてオーバーロードを介して要求できますct.Register()
。コールバックは通常保存され、キャンセルが要求されたときに実行されますが、キャンセルが要求された後にコールバックが登録されている場合、コールバックは現在のスレッドですぐに実行されるか、該当する場合は現在のスレッドを介して実行されSend()
ます
SynchronizationContext
。
コールバックが に登録されているCancellationToken
場合、返されるオブジェクトはCancellationTokenRegistration
です。これは軽い構造体型でありIDiposable
、この登録オブジェクトを破棄すると、コールバックが登録解除されます。Dispose()
メソッドが返された後、登録されたコールバックが実行されておらず、その後開始されないことが保証さ
れます。この結果
CancellationTokenRegistration.Dispose()
、コールバックが現在実行中の場合はブロックする必要があります。したがって、登録されたすべてのコールバックは高速である必要があり、長時間ブロックされることはありません。
Mike Liddell による別の関連ドキュメントは、"Using Cancellation Support in .NET Framework 4" (UsingCancellationinNET4.pdf)です。
更新されました。これは参照ソースで確認できます。
CancellationTokenSource
キャンセル コールバックはではなく に登録されることに注意することも重要CancellationToken
です。そのため、CancellationTokenRegistration.Dispose()
スコープが正しく設定されていない場合、登録は親CancellationTokenSource
オブジェクトの存続期間中アクティブのままになります。これにより、非同期操作のスコープが終了したときに予期しないコールバックが発生する可能性があります。たとえば、次のようになります。
async Task TestAsync(WebClient wc, CancellationToken token)
{
token.Register(() => wc.CancelAsync());
await wc.DownloadStringAsync(new Uri("http://www.hamster.com"));
}
// CancellationTokenSource.Cancel() may still get called later,
// in which case wc.CancelAsync() will be invoked too
CancellationTokenRegistration
したがって、 で使い捨てをスコープする(または で明示的にusing
呼び出す) ことが重要です。CancellationTokenRegistration.Dispose()
try/finally