【问题标题】:F# can't catch TimeoutExceptionF# 无法捕获 TimeoutException
【发布时间】:2014-12-01 12:32:28
【问题描述】:

我的问题很简单。请看截图:

怎么会这样?我明确地将 Async.RunSyncronously 调用放入try ... with

【问题讨论】:

  • 也许我没有正确理解,但我认为通过这样做,我执行以下操作:async 启动新线程,并且该线程等待 operation 完成。这对我来说很好。我可以改用let!,但let 不允许指定超时,这就是我的目标。
  • 是的,确实如此。问题可能会出现,因为我的operation 调用了一些 COM 对象方法,而这始终是故障的根源。但我不能确定。

标签: exception f# timeout try-catch


【解决方案1】:

试试这个:

let withTimeout (timeOut: option<int>) (operation: Async<'x>) : Async<option<'x>> =
  match timeOut with
   | None -> async {
       let! result = operation
       return Some result
     }
   | Some timeOut -> async {
       let! child = Async.StartChild (operation, timeOut)
       try
         let! result = child
         return Some result
       with :? System.TimeoutException ->
         return None
     }

您不应该在async 块中使用Async.RunSynchronously,因为这样做会导致对本机线程的次优使用,并可能导致stack overflowsAsync.RunSynchronously 用于从此类计算之外运行 Async 计算。在async 块中,您可以使用普通的let!do! 或例如Async.StartChild 来运行Async 计算。这样可以更有效地使用本机线程,并且不会遇到类似的潜在堆栈溢出问题。

【讨论】:

  • +1 非常感谢,这行得通,我会使用你的版本。虽然我的版本为什么不起作用仍然很有趣
【解决方案2】:

try/with 在 F# 异步工作流中不直接映射到受 CLR 保护的块 - 相反,如果在用户代码中引发异常,库代码将捕获它并重新路由到最近的错误延续(可以是 with blockfinally blockAsync.StartWithContinuations 中提供的自定义错误延续等...)。这导致调试器可能会报告用户代码中的未处理异常,这些异常可以稍后处理和处理。

下面的代码段在调试器中报告了类似的错误,但执行成功完成

let error (): int = raise (System.TimeoutException())

let run() = async {
    try 
        let result = error()
        return result
    with
    :? System.TimeoutException -> return -1
}

let r = Async.RunSynchronously (run())
printfn "%d" r

【讨论】:

  • 哇,这真的很有趣。这是异步计算表达式实现的副作用吗?您能否建议我捕捉该该死的异常的最佳方法是什么?我应该把它包装成StartWithContinuations吗?
猜你喜欢
  • 2023-03-30
  • 2019-12-06
  • 2019-12-30
  • 2017-05-25
  • 1970-01-01
  • 2012-08-08
  • 2012-11-09
  • 2011-03-14
  • 2012-03-15
相关资源
最近更新 更多