Async.Начать с тайм-аутом и отменой Token? - PullRequest
0 голосов
/ 04 марта 2019

У меня есть вычисление Async<'T>, которое я хочу выполнить, и получаю результат 'T.

У меня только два требования:

  1. После определенного timeout:TimeSpanпрошло, я хочу, чтобы вычисление / ввод-вывод было прервано.
  2. Я хочу запустить его с cancellationToken на всякий случай, если я хочу прервать его до того, как пройдет timeout.

Согласно моему требованию (1) выше, вы можете подумать, что Async.StartChild является хорошим кандидатом, поскольку он принимает параметр timeout, однако он не принимает параметр cancellationToken!

Кажется, чтодругие Async. методы в API, которые принимают cancellationToken, либо не возвращают ничего (поэтому я не могу дождаться результата), либо работают только для Async<unit>, либо не позволяют мне комбинировать его с Async..StartChild для выполнения обоих моих требований.

Кроме того, мне нужно реализовать это внутри блока async{}, что означает использование Async.RunSynchronously внутри него (на случай, если вы предложите это ) будет выглядеть проблематично или некрасиво.

Я что-то пропускаю?

Спасибо!

1 Ответ

0 голосов
/ 05 марта 2019

Как указано в комментариях hvester , вам не нужно передавать CancellationToken при запуске вычисления Child.Он будет передан Родителю и отменит оба, см. Например здесь .

let work dueTime = async{
    do! Async.Sleep dueTime
    printfn "Done" }
let workWithTimeOut timeForWork timeOut = async{
    let! comp = Async.StartChild(work timeForWork, timeOut)
    return! comp }

workWithTimeOut 200 400 |> Async.Start // prints "Done"
workWithTimeOut 400 200 |> Async.Start // throws System.TimeoutException

let cts = new System.Threading.CancellationTokenSource()   
Async.Start(workWithTimeOut 400 200, cts.Token)
System.Threading.Thread.Sleep 100
cts.Cancel() // throws System.OperationCanceledException
...