[英]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
应用程序在运行时立即崩溃。 这对我来说没有意义,原因有两个:
Async.Start
冒泡(渲染try ... with
没有意义,但是它存在于第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.