簡體   English   中英

執行外部進程時,超時不適用於 F# Async.RunSynchronously

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM