надуманный пример, но предположим, что у меня есть следующие в методе асинхронном:CancellationTokenRegistrations
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);
}
В этом случае обратный вызов не называется, по-видимому, потому что исключение из 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' в' Callback' –
. Связанный: http://stackoverflow.com/questions/21367695/why- cancelationtokenregistration-exists-and-why-do-it-implement-idisposable –
@MattSmith - я хотел, чтобы «Обратный звонок» вызывался только в том случае, если во время 'SomethingThatMightThrow() запрашивается отмена; ожидание Task.Delay (10000, cts.Token); 'block. – Duncan