【发布时间】:2014-08-29 11:10:28
【问题描述】:
人为的例子,但假设我在异步方法中有以下内容:
var cts = new CancellationTokenSource();
cts.CancelAfter(2000);
cts.Token.Register(Callback);
SomethingThatMightThrow();
await Task.Delay(10000, cts.Token);
只要几秒钟后回调被调用,这将按预期工作。但是,我想在Task.Delay之后处理注册,所以假设我进行以下修改:
var cts = new CancellationTokenSource();
cts.CancelAfter(2000);
using (cts.Token.Register(Callback))
{
SomethingThatMightThrow();
await Task.Delay(10000, cts.Token);
}
在这种情况下,不调用 Callback,可能是因为来自 await Task.Delay... 的异常导致注册在被调用之前被释放。
确保Callback 在取消时被调用并且注册总是被处理的最佳方式是什么?
我确实想到了以下几点,但我不确定它有多强大:
var cts = new CancellationTokenSource();
cts.CancelAfter(2000);
var ctr = cts.Token.Register(Callback);
try
{
SomethingThatMightThrow();
await Task.Delay(10000, cts.Token);
}
finally
{
if (!cts.Token.IsCancellationRequested)
ctr.Dispose();
}
【问题讨论】:
-
不清楚您是否总是希望/期望
Callback被调用,或者代码中是否有某个点之后您将不再需要回调即使 CancelAfter 时间到了也会被调用。如果您总是希望调用回调(即使您的其余代码已完成),只需在Callback中处理CancellationTokenRegistration -
@MattSmith - 我希望只有在
SomethingThatMightThrow(); await Task.Delay(10000, cts.Token);块期间请求取消时才调用Callback。 -
Task.Delay 和 Token.Register 都在令牌上注册回调。 Task.Delay 的回调首先被调用(这会导致 await 完成并且 using 语句完成并且 CancellationTokenRegistration 被释放)。因此,当它到达下一个回调时,它已经被取消注册了。
-
@MattSmith - 是的,这就是我想象的事情,这就是我的问题的真正目的 - 鉴于情况如此,因此我提供的第二个代码 sn-p 不起作用(因为@ 987654333@ 没有被调用),最好的选择是什么?
标签: c# async-await idisposable using cancellationtokensource