簡體   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