Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
783 views
in Technique[技术] by (71.8m points)

f# - mailboxprocessor does not terminate

I have a timeout exception (and I really intend to set a timeout) inside a message loop and I have tried to catch it as follows

let printerAgent = MailboxProcessor.Start(fun inbox-> 
    // the message processing function
    let rec messageLoop() = async{
        try
            // read a message
            let! msg = inbox.Receive 30000
            // process a message
            match msg with
            | Message text ->
                sw.WriteLine("{0}: {1}", DateTime.UtcNow.ToShortTimeString(), text)
                printfn "%s" text
                // loop to top
                return! messageLoop()  
            | Shutdown replyChannel ->
                replyChannel.Reply()
                // We do NOT do return! messageLoop() here
        with 
        | exc -> 
            printfn "%s" exc.Message
        }
    // start the loop 
    messageLoop() 
    )

and I can see the timout message printed in the console, but the program never ends: what am I missing?

This is how I'm calling the printerAgent in my code

printerAgent.PostAndReply( (fun replyChannel -> Shutdown replyChannel), 10000)

Notice that with inbox.Receive() it eventually terminates fine after a few minutes but my objective is setting a timeout (for example of 30 seconds) instead.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think I see the conceptual problem. I can't terminate the message loop before I receive the final shutdown message (otherwise all the following printerAgent.Post messages sent by the program will simply remain unprocessed in the queue, without blocking the program with any error, and the final shutdown message, sent by a printerAgent.PostAndReply will timeout, also without blocking the program with any error). I should return the message loop so it can actually continue after the timeout exactly as it happens for a normal received message:

with 
| exc -> 
    printfn "%s" exc.Message
    return! messageLoop() // important! I guess I can't really terminate the message loop from here

And at this point the program terminates in the same time: I just see a lot of Timeout of Mailbox.Receive printed in the console (every n=30 seconds while the message loop is idling waiting to receive a message, so they can be informative about the elapsed time).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...