[英]Timeout doesn't work for F# Async.RunSynchronously when executing an external process
使用下面的代碼啟動一個可能很慢或掛起的過程不會導致超時:
open System.Diagnostics
[<EntryPoint>]
let main argv =
Async.RunSynchronously(
async {
use proc = Process.Start(@"SlowProcess.exe")
proc.WaitForExit()
}, timeout = 2000)
0
解決方法當然是在調用WaitForExit
時使用超時,但我很好奇為什么Async.RunSynchronously
超時在這種特定情況下不起作用。
F# 異步工作流的取消方式是協作的——它永遠不會強行終止線程。 它會自動傳播取消令牌,將其傳遞給支持該令牌的操作,並在每次 F# 異步工作流基礎架構有機會時檢查取消(通常在使用let!
運行代碼之前和完成之后)。 這意味着阻塞代碼不會被取消。 一個更小的例子可以說明這一點:
let work = async {
try
printfn "Going to sleep"
Thread.Sleep(10000)
printfn "Waking up"
finally
printfn "All completed"
}
如果你運行它並立即取消它,它會打印“Going to sleep”,然后你只會在 10 秒后得到“All completed”——因為Thread.Sleep
調用是同步的。
如果你想在工作流被取消時終止進程,你應該能夠顯式注冊一個取消處理程序並使用Kill
方法來停止進程 - 我沒有測試過這個(我沒有合適的慢速進程, ):但是這樣的事情應該可以解決問題:
let work = async {
let! tok = Async.CancellationToken
use proc = Process.Start(@"SlowProcess.exe")
tok.Register(fun () -> proc.Kill()) |> ignore
proc.WaitForExit()
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.