[英]Timeout doesn't work for F# Async.RunSynchronously when executing an external process
Starting a potentially slow or hanging process with the code below, will not result in a timeout:使用下面的代码启动一个可能很慢或挂起的过程不会导致超时:
open System.Diagnostics
[<EntryPoint>]
let main argv =
Async.RunSynchronously(
async {
use proc = Process.Start(@"SlowProcess.exe")
proc.WaitForExit()
}, timeout = 2000)
0
The workaround is of course to use a timeout in the call to WaitForExit
, but I'm curious about why the Async.RunSynchronously
timeout doesn't work in this specific case.解决方法当然是在调用
WaitForExit
时使用超时,但我很好奇为什么Async.RunSynchronously
超时在这种特定情况下不起作用。
The way cancellation in F# asynchronous workflows works is that it is collaborative - it will never forcefully kill the thread. F# 异步工作流的取消方式是协作的——它永远不会强行终止线程。 It propagates the cancellation token automatically, passes it to operations that support that and checks for cancellation every time the F# async workflow infrastructure gets a chance (typically before running code using
let!
and after it completes).它会自动传播取消令牌,将其传递给支持该令牌的操作,并在每次 F# 异步工作流基础架构有机会时检查取消(通常在使用
let!
运行代码之前和完成之后)。 This means that blocking code is not cancelled.这意味着阻塞代码不会被取消。 A smaller example that illustrates this would be:
一个更小的例子可以说明这一点:
let work = async {
try
printfn "Going to sleep"
Thread.Sleep(10000)
printfn "Waking up"
finally
printfn "All completed"
}
If you run this and cancel it immediately, it will print "Going to sleep" and then you'll only get "All completed" after 10 seconds - because the Thread.Sleep
call is synchronous.如果你运行它并立即取消它,它会打印“Going to sleep”,然后你只会在 10 秒后得到“All completed”——因为
Thread.Sleep
调用是同步的。
If you want to kill the process when the workflow is cancelled, you should be able to explicitly register a cancellation handler and use the Kill
method to stop the process - I have not tested this (I don't have a suitable slow process around,): but something like this should do the trick:如果你想在工作流被取消时终止进程,你应该能够显式注册一个取消处理程序并使用
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.