繁体   English   中英

为什么Async.Start似乎传播无法捕获的异常?

[英]Why does Async.Start seemingly propagate uncatchable exceptions?

考虑这个控制台应用:

let throwAsync = 
  async { failwith "" }

[<EntryPoint>]
let main argv =
  try Async.Start throwAsync
  with _ -> printfn "Failed"
  System.Console.Read() |> ignore
  0

应用程序在运行时立即崩溃。 这对我来说没有意义,原因有两个:

  1. AFAIK(例如这个博客文章 )异常不应该通过Async.Start冒泡(渲染try ... with没有意义,但是它存在于第2点)
  2. (令人惊讶的)抛出代码被try ... with包围,但异常未被捕获(它永远不会打印"Failed" ,同样,应用程序崩溃)。

这是怎么回事?

异步块执行的线程池线程抛出异常。

所以,是的,这意味着异常不会传播到运行Async.Start的线程,并且永远不会命中try-with块。 而且,这意味着异常现在被抛到其他地方,并且没有任何异常处理它将使您的应用程序崩溃。

引用MSDN

线程池线程中未处理的异常终止进程。 此规则有三个例外:

  • 由于调用了Thread.Abort因此在线程池线程中抛出System.Threading.ThreadAbortException
  • 由于正在卸载应用程序域,因此在线程池线程中抛出System.AppDomainUnloadedException
  • 公共语言运行库或主机进程终止该线程。

有关更多信息,请参阅托管线程中的例外

使用Async.Start执行时, try无法在async捕获异常,因为它们分叉在不同的线程中。 如果要捕获它,可以使用Async.RunSynchronously或在另一个async

let throwAsync = async { failwith "I was not caught!" }

let catchAsync = async {
    try 
        do! throwAsync
    with _-> printfn "caught inside async!"
}

[<EntryPoint>]
let main argv =
    try throwAsync |> Async.RunSynchronously 
    with _ -> printfn "caught outside!"
    try catchAsync |> Async.Start 
    with _ -> printfn "I did not catch it either!"
    System.Console.Read() |> ignore
    printfn "finishing!"
    0

输出:

caught outside!
caught inside async!
finishing!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM