【发布时间】:2019-04-13 07:19:17
【问题描述】:
考虑以下代码:
open System
open System.Diagnostics
open System.Threading
open System.Threading.Tasks
type Async with
static member WithTimeout (timeout: int) operation =
async {
let! child = Async.StartChild (operation, timeout)
try
let! _result = child
return true
with :? TimeoutException -> return false
}
static member WithTaskTimeout<'T> (timeout: int) (operation: Async<'T>) = async {
let delay = Task.Delay(timeout)
let! task = Task.WhenAny(operation |> Async.StartAsTask :> Task, delay) |> Async.AwaitTask
if task = delay then
return false
else
return true
}
[<EntryPoint>]
let main _ =
let syncSleep = async {
Thread.Sleep(4000)
return 1
}
let asyncSleep = async {
do! Async.Sleep(4000)
return 1
}
let run name async =
let time action prefix =
let sw = Stopwatch.StartNew()
let result = action |> Async.RunSynchronously
sw.Stop()
printfn "%s | %s returned %O. Elapsed: %O" prefix name result sw.Elapsed
time (async |> Async.WithTimeout 2000) "Async"
time (async |> Async.WithTaskTimeout 2000) "Task "
run "Thread.Sleep" syncSleep
run "Async.Sleep " asyncSleep
0
在 Mono 5.18.1.3 上,它会产生以下输出:
Async | Thread.Sleep returned False. Elapsed: 00:00:04
Task | Thread.Sleep returned False. Elapsed: 00:00:02
Async | Async.Sleep returned False. Elapsed: 00:00:02
Task | Async.Sleep returned False. Elapsed: 00:00:02
所以当子异步内部有同步等待时,Async.StartChild 不是在超时过去时返回,而是在内部异步完成时返回。
同时,在两个调用中都带有超时的基于任务的执行仅在超时后才返回。
为什么Async.StartChild 会这样?
【问题讨论】:
标签: asynchronous f#