假设我有一些系统“BlackBox”,我无法改变,我想尝试用它做2秒,如果它不能完成 - 停止并继续其他应用:
let log msg =
let timestamp = (System.DateTime.UtcNow.ToString("o"))
printfn "%s: %s" timestamp msg
type BlackBox() =
let tcs = new System.Threading.Tasks.TaskCompletionSource<bool>()
let work () = async {
log "work started"
let! result = tcs.Task |> Async.AwaitTask
log "work finished"
return result }
member x.DoWork () = work ()
member x.SetResult () = tcs.TrySetResult(true)
let tryDoWork (box:BlackBox) = async {
try
log "operration starting with 2sec timeout"
Async.RunSynchronously(box.DoWork(), timeout = 2000) |> ignore
log "operration succeeded"
with
| ex -> log "operation timedout" }
let sut = BlackBox()
tryDoWork sut |> Async.Start
log "waiting 5sec before setting task result"
Async.Sleep 5000 |> Async.RunSynchronously
log "setting task result"
sut.SetResult() |> ignore
// Output is:
// ------------------------------------
// 2016-02-24T16:45:11.0302884Z: waiting 5sec before setting task result
// 2016-02-24T16:45:11.0302884Z: operration starting with 2sec timeout
// 2016-02-24T16:45:11.0351932Z: work started
// 2016-02-24T16:45:16.0322394Z: setting task result
// 2016-02-24T16:45:16.0351731Z: work finished
// 2016-02-24T16:45:16.0361528Z: operation timedout
Async.RunSyncronously with timeout在2秒后抛出TimeoutException,但不是在这种情况下,因为内部BlackBox正在等待Task完成。
答案 0 :(得分:2)
TCS(来自@ Carsten的评论)对我有用,因为我无法访问BlackBox内部,并且无法在不更改应用程序的整个设计且需要添加超时的机制的情况下更改它,不需要取消更长的任务
其他提议的事情是:
@kevin:
snippet by Eirik Tsarpalis和
Async.AwaitIAsyncResult
并且@kevin注意到我的例子没有按预期工作的原因是
RunXynchronously with timeout依赖于给定的async可取消