F # не завершается при возникновении ошибок во время выполнения внутри блока asyn c - PullRequest
0 голосов
/ 17 апреля 2020

Когда у меня возникает ошибка времени выполнения, подобная этой

type Msg = Any

type Agent() =

    let agent =
        MailboxProcessor.Start(fun inbox ->
            let rec messageLoop (oldState) =
                async {

                    let! msg = inbox.Receive()
                    printfn "1"

                    match msg with
                    | Any ->

                        printfn "2"

                        let neverFound=
                          oldState
                          |> List.find (fun x -> x = 42)

                        printfn "3" // <- never happens, because I tried to find something that does not exists
                        return! messageLoop (oldState @ [neverFound])
                }

            printfn "0"
            messageLoop ([ 1; 2; 3 ]))

    member __.Post a = agent.Post a

let agent = Agent()
agent.Post ( Any)

, она делает cra sh, ошибка совершенно тихая, но если я явно пытаюсь .. with:

type Msg = Any

type Agent() =

    let agent =
        MailboxProcessor.Start(fun inbox ->
            let rec messageLoop (oldState) =
                async {

                    let! msg = inbox.Receive()
                    printfn "1"

                    match msg with
                    | Any ->

                        printfn "2"
                        try
                          let neverFound=
                            oldState
                            |> List.find (fun x -> x = 42)

                          printfn "3" 
                          return! messageLoop (oldState @ [neverFound])

                        with e ->
                          printfn "%A" e <-- does print
                          printfn "4"
                }

            printfn "0"
            messageLoop ([ 1; 2; 3 ]))

    member __.Post a = agent.Post a

let agent = Agent()
agent.Post ( Any)

if обнаруживает ошибку.

Это не единственное место, где это происходит, по-видимому, ошибки, которые происходят внутри asyn c, молчат? Как я могу предотвратить это? Есть ли флаг, который можно запустить без скрытых ошибок? или может быть глобальный asyn c обработчик ошибок?

1 Ответ

1 голос
/ 17 апреля 2020

Это по замыслу. Вы не ожидаете, что актеры взломают sh при получении сообщения.

Start по сути:

   Async.Start(async { try do! body x with exn -> trigger exn })

Так что если вы выставите MailboxProcessor.Error с

member _.Error  = agent.Error

и послушайте его:

agent.Error 
|> Observable.subscribe(fun (err) -> printfn "Oh no, an error: %s" err.Message) 
|> ignore

вы действительно увидите:

Oh no, an error: An index satisfying the predicate was not found in the collection.
...