Возможно, у меня здесь 2 вопроса вместо одного, но тем не менее.
Я реализую совместную отмену, как предложено здесь. Вот мой тестовый код:
type Async with
static member Isolate(f : CancellationToken -> Async<'T>) : Async<'T> =
async {
let! ct = Async.CancellationToken
let isolatedTask = Async.StartAsTask(f ct)
return! Async.AwaitTask isolatedTask
}
let testLoop (ct: CancellationToken) = async {
let rec next ix =
if ct.IsCancellationRequested then ()
else
printf "%i.." ix
Thread.Sleep 10
next (ix+1)
next 1
}
let cancellationSource = new CancellationTokenSource()
let onDone () = printfn "!! DONE"
let onError _ = printfn "!! ERROR"
let onCancel _ = printfn "!! CANCEL"
Async.StartWithContinuations (Async.Isolate testLoop, onDone, onError, onCancel, cancellationSource.Token)
Thread.Sleep(100)
cancellationSource.Cancel ()
Thread.Sleep(500)
Как видите, я запускаю async с продолжениями done, cancel и error. Если я запущу этот код как есть, я получу следующий вывод:
1..2..3..4..5..6..7..8..!! СДЕЛАНО
Если я немного обновлю метод Isolate
следующим образом:
static member Isolate(f : CancellationToken -> Async<'T>) : Async<'T> =
async {
let! ct = Async.CancellationToken
let isolatedTask = Async.StartAsTask(f ct)
let! x = Async.AwaitTask isolatedTask
x
}
Я получаю ожидаемый (сам по себе) вывод:
1..2..3..4..5..6..7..!! ОТМЕНА
Почему у нас такая разница в поведении?
Можно ли прервать testLoop
, если он не отменяется в течение некоторого тайм-аута?