This is an agent framework based on on F# MailboxProcessors. It supports agents, workers, error management, timeout management and hot swapping of code. The framework is described here: http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx
Here is some code to give you an idea:
// A worker is an agent that doesn't keep a private state
let echo = spawnWorker (fun s -> printfn "%s" s)
echo <-- "Hello guys!"
// Given that it is stateless, multiple identical ones can process messages at the same time (look at last parameter)
let parallelEcho = spawnParallelWorker (fun s -> printfn "%s" s) 10
parallelEcho <-- "Hello guys!"
// The difference is easily seen by printing out the thread the message is processed on (damn I cannot reuse variable names)
let tprint s = printfn "%s running on thread %i" s Thread.CurrentThread.ManagedThreadId
let echo1 = spawnWorker (fun s -> tprint s)
// The Sleep instruction is helpful in really running the workers on multiple threads (if it's too fast the thread pool reuses the same thread)
let parallelEcho1 = spawnParallelWorker(fun s -> tprint s; Thread.Sleep(300)) 10
// All the msg processing runs on a single thread
let messages =
"a";"b";"c";"d";"e";"f";"g";"h";"i";"l";"m";"n";"o";"p";"q";"r";"s";"t";"b";"c";"d";"e";"f";"g";"h";"i";"l";"m";"n";"o";"p";"q";"r";"s";"t"messages |> Seq.iter (fun msg -> echo1 <-- msg)
// It now uses multiple threads (max of 10 as from last parameter to spawnParallelWorker)
messages |> Seq.iter (fun msg -> parallelEcho1 <-- msg)
// Agents are like workers, but they keep an internal state
let counter = spawnAgent (fun msg state -> state + msg) 0
// Now printing out stuff
let counter1 = spawnAgent (fun msg state -> printfn "From %i to %i" state (state + msg); state + msg) 0
counter1 <-- 3
counter1 <-- 4
// Ohh, and you can restart agents (wasn't this supposed to take ints?? :-) )
counter1 <-! Restart
counter1 <-- 3
// If you try to send the wrong type of message, it won't even compile, as below
// counter1 <-- "fst"
// If there is an error in the message processing, by default you get notified with eprintfn with as much info as possible about the error
let errorProneCounter = spawnAgent (fun i s -> printfn "The state was %i and the result was %i" s (s / i); s / i) 100
errorProneCounter <-- 20
errorProneCounter <-- 0