Unifying Task<T> and F# MailboxProcessor exception handling -


when using task<t>, exception during execution of task thrown during task.wait(); when using f#'s mailboxprocessor, exception gets swallowed , needs explicitly dealt per this question.

this difference makes difficult expose f# agents c# code via task. example, agent:

type internal incrementmessage =      increment of int * asyncreplychannel<int>  type incrementagent() =     let counter = agent.start(fun agent ->          let rec loop() = async { let! increment(msg, replychannel) = agent.receive()                                 match msg                                  | int.maxvalue -> return! failwith "boom!"                                 | _ -> replychannel.reply (i + 1)                                             return! loop() }          loop())      member x.postandasyncreply =         async.startastask (counter.postandasyncreply (fun channel -> increment(i, channel))) 

can called c#, exception not returned c#:

[test] public void exceptionhandling() {     //     // tpl exception behaviour     //     var task = task.factory.startnew<int>(() => { throw new exception("boom!"); });      try     {         task.wait();     }     catch(aggregateexception e)     {         // exception available here         console.writeline("task failed {0}", e.innerexception.message);     }      //     // f# mailboxprocessor exception behaviour     //     var incagent = new incrementagent();     task = incagent.postandasyncreply(int.maxvalue);      try     {         task.wait(); // deadlock here     }     catch (aggregateexception e)     {         console.writeline("agent failed {0}", e.innerexception.message);     } } 

instead of getting exception, c# code hangs @ task.wait(). there way f# agent behave task? if not, seems there limited use in exposing f# agents other .net code.

one way handle have agent return du error case. raise exception outside agent.

type internal incrementresponse =     | response of int     | error of exn  type internal incrementmessage =      | increment of int * asyncreplychannel<incrementresponse>  type incrementagent() =     let counter = agent.start(fun agent ->          let rec loop() =            async {              let! increment(msg, replychannel) = agent.receive()             match msg              | int.maxvalue -> replychannel.reply (error (failure "boom!"))             | _ -> replychannel.reply (response(i + 1))             return! loop()            }         loop())      member x.postandasyncreply =         async.startastask (           async {             let! res = counter.postandasyncreply (fun channel -> increment(i, channel))             match res             | response -> return             | error e -> return (raise e)           }         ) 

Comments

Popular posts from this blog

java - Play! framework 2.0: How to display multiple image? -

gmail - Is there any documentation for read-only access to the Google Contacts API? -

php - Controller/JToolBar not working in Joomla 2.5 -