C# Rx库是否忽略处理它创建的CancellationTokenSources?
Rx库包括接受lambda参数的操作员,其中一些lambda配有由库本身控制的控制器。这些运算符的一些示例是,C# Rx库是否忽略处理它创建的CancellationTokenSources?,c#,system.reactive,cancellationtokensource,cancellation-token,rx.net,C#,System.reactive,Cancellationtokensource,Cancellation Token,Rx.net,Rx库包括接受lambda参数的操作员,其中一些lambda配有由库本身控制的控制器。这些运算符的一些示例是,StartAsync和Create: // Converts an asynchronous action into an observable sequence. Each subscription // to the resulting sequence causes the action to be started. The CancellationToken // passed
StartAsync
和Create
:
// Converts an asynchronous action into an observable sequence. Each subscription
// to the resulting sequence causes the action to be started. The CancellationToken
// passed to the asynchronous action is tied to the observable sequence's subscription
// that triggered the action's invocation and can be used for best-effort cancellation.
public static IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync);
输出:
令牌已取消
可观察到的结果被终止
IsCancellationRequested:True
IsDisposed:False
(.NET Framework版本,具有不同名称的专用字段)
在异步操作被取消且可观察对象终止后的半秒钟内,将检查捕获的CancellationToken
。\u disposed
字段的值为false
,表示关联的CancellationTokenSource
的Dispose
方法未被调用。是我做错了什么,还是Rx库确实忽略了处理它创建的CancellationTokenSource
s
.NET 5.0.1、System.Responsive 5.0.0、C#9文档详细说明了这种情况:它说明了实现
IDisposable的任何类型。实际上,CancellationTokenSource
只有在您使用过.CancelAfter(…)
或CancellationToken.WaitHandle
时才需要处理,即使这样,计时器在启动时也会自动清理,大多数人也不需要处理互斥锁(因为这样做通常会引入竞争)。它有点像Task.Dispose
:它在API中,但在API中大部分时间都没有被调用practice@canton7问题在于任务.Dispose
明确指出:“但是,特别是如果您的应用程序针对.NET Framework 4.5或更高版本,则无需调用Dispose,除非性能或可伸缩性测试表明,根据您的使用模式,您的应用程序的性能将通过处理任务而得到改善。“。文档中没有关于CancellationTokenSource.Dispose
方法的这些细节!我说这“有点像”任务。Dispose
。尽管是API的一部分,但有很多类型的处理在实践中通常是不必要的,不管文档怎么说。CTS和互斥体一样,通常很讨厌正确地进行处理,因为除了极少数情况外,实际上并不需要进行处理,所以一般的惯例是不麻烦的。@canton7在这种情况下,该方法的文档似乎是错误的,应该使用“Always”等措辞不太强硬的语言更新文档。否则,我们应该停止一般的信任吗?总是带着一撮盐去看MSDN文档!它们很好,而且越来越好,但并不完美。
CancellationToken capturedToken = default;
var subscription = Observable.FromAsync(async token =>
{
capturedToken = token;
token.Register(() => Console.WriteLine("Token canceled"));
await Task.Delay(Timeout.Infinite, token);
})
.TakeUntil(Observable.Timer(TimeSpan.FromMilliseconds(500)))
.Finally(() => Console.WriteLine("The observable was terminated"))
.Subscribe();
Thread.Sleep(1000);
var cts = (CancellationTokenSource)(typeof(CancellationToken)
.GetField("_source", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(capturedToken));
bool disposed = (bool)(typeof(CancellationTokenSource)
.GetField("_disposed", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(cts));
Console.WriteLine($"IsCancellationRequested: {cts.IsCancellationRequested}");
Console.WriteLine($"IsDisposed: {disposed}");