簡體   English   中英

失敗后重新啟動MailboxProcessor?

[英]Restart MailboxProcessor after failure?

我試圖通過MailboxProcessor<'Msg>類開始使用F#中的代理,我很快意識到我沒有適當的處理異常的方法。 在Haskellian的世界中,不會有任何例外,因此處理問題的正確方法是簡單地將其作為響應案例提供。 因此,座席可以回復以下內容:

type AgentResponse =
    | HandledData of string
    | InvalidData of string

然后可以調用代理的.PostAndReply方法,並獲取一個InvalidData其中包含指示數據為何無效的消息。 但是,這不是Haskell,有時會發生異常。 因此,如果我這樣做:

let agent =
    new MailboxProcessor<string * AsyncReplyChannel<AgentResponse>>(fun inbox ->
        async {
            while true do
                let! (msg, replyChannel) = inbox.Receive()
                if msg = "die" then failwith "Unknown exception encountered!"
                else replyChannel.Reply(HandledData(msg))
        })

agent.Start()
agent.PostAndReply (fun rc -> "die", rc)
agent.PostAndReply (fun rc -> "Test", rc)

agent.PostAndReply的第二次調用無限期阻塞。 當不使用AsyncReplyChannel並因此僅調用agent.Post ,調用不會阻塞,但是一旦代理遇到異常,新消息就只會留在隊列中。 在這兩種情況下,都無法重新啟動代理,因為agent.Start函數在再次InvalidOperationException時會返回InvalidOperationException ,而處理此問題的自然方法似乎是創建一個具有純凈狀態的新代理,但是所有排隊的消息都會丟失。

除了在try..with包裝代理的整個主體try..with ,還有什么好方法可以讓代理在發生異常后繼續運行? 或者,是否已經建立了可以指出我的“標准”處理方式?

您在Haskell中確實有例外:嘗試在ghci中使用Data.List.head []

不幸的是,在Haskell或F#中,缺少依賴類型意味着我們可以編寫沒有計算意義的類型正確的代碼。

實際上,用try ... with塊包裝不是處理異常的好主意。 您不需要包裝整個正文,而只是包裝代碼的非純部分。

然后,按照經典方法,您將產生一個使用適當的構造函數生成的值。

一個可能的選項是類似於在此問題上 Tomas Petricek定義的HandlingMailbox的幫助程序類型,該類型重復運行代理程序的主體:

type ResilientMailbox<'T> private(f:ResilientMailbox<'T> -> Async<unit>) as self =
    let event = Event<_>()
    let inbox = new MailboxProcessor<_>(fun _inbox ->
        let rec loop() = async {
            try
                return! f self
            with e ->
                event.Trigger(e)
                return! loop()
            }
        loop())
    member __.OnError = event.Publish
    member __.Start() = inbox.Start()
    member __.Receive() = inbox.Receive()
    member __.Post(v:'T) = inbox.Post(v)
    static member Start(f) =
        let mbox = new ResilientMailbox<_>(f)
        mbox.Start()
        mbox

可以像正常的MailboxProcessor一樣啟動和運行它,但是如果提供的代理主體引發異常,它將重新運行。

編輯:更改內部MailboxProcessor以使用遞歸函數而不是while true do..塊; 目標函數正常返回時,先前的代碼不會停止運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM