.net - 执行外部进程时超时不适用于 F# Async.RunSynchronously
问题描述
使用下面的代码启动一个可能很慢或挂起的过程不会导致超时:
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()
}
推荐阅读
- java - Hibernate Entity Manager - QuerySyntaxException:FooBar 未映射
- c# - 在 C# 中覆盖索引器和使用方法
- typescript - 向已编译的打字稿文件添加前导注释
- javascript - Javascript按复合键排序obj
- azure-active-directory - Microsoft 图形 API 使用客户端密码使用令牌身份验证发送电子邮件。我已将令牌粘贴到 https://jwt.ms/ 但缺少范围
- reactjs - 有 url 参数时路由不匹配
- firebase - Firebase Firestore 安全规则 - 根据资源读取所有嵌套文档(但它为空)
- python - os.system('TASKKILL /F /IM EXCEL.exe') 在 python 中
- r - 将数据标签添加到 ggplot 图例
- python - 在 pycharm 中安装包