问题
I have an Async<'T>
computation that I want to run, and obtain the result 'T
.
I only have two requirements:
- After certain
timeout:TimeSpan
has passed, I want the computation/IO to be aborted. - I want to run it with a
cancellationToken
just in case I want to abort it beforetimeout
has passed.
According to my requirement (1) above, you might think that Async.StartChild
is a good candidate because it accepts a timeout parameter, however, it doesn't accept a cancellationToken parameter!
It seems that the other Async.
methods in the API that accept a cancellationToken either don't return anything (so I cannot await for the result), or only work for Async<unit>
, or don't allow me a way to combine it with Async.StartChild to achieve both of my requirements.
Also, I need to implement this inside an async{}
block, which means that using Async.RunSynchronously
inside it (just in case you suggest this) would look either problematic or ugly.
Am I overlooking anything?
Thanks!
回答1:
As mentioned in the comments by hvester, you do not need to pass a CancellationToken when starting the Child computation. It will be shared by the Parent and would cancel both, see for example here.
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
来源:https://stackoverflow.com/questions/54978550/async-start-with-timeout-and-cancellationtoken