假设我有一些无法更改的系统“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 超时会在 2 秒后抛出 TimeoutException,但在这种情况下不会,因为 BlackBox 内部正在等待任务完成。
最佳答案
TCS(来自 @Carsten 的评论)适合我,因为我无法访问 BlackBox 内部结构,并且无法在不更改应用程序的整个设计的情况下更改它,并且需要添加超时机制,不需要取消较长的任务
其他提议的事情是:
@凯文:
snippet by Eirik Tsarpalis and
Async.AwaitIAsyncResult
@kevin 注意到我的示例未按预期工作的原因是
RunSynchronously with a timeout relies on the given async being cancelable
关于asynchronous - 如何通过超时停止等待 TaskCompletionSource 周围的异步包装器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35608947/