Wednesday, May 2, 2012 at 9:22PM

Using concurrent processing techniques there will be times multiple threads will update an Entity at the same time. This update could be on the database level, in memory, or over the network; when there are multiple thread updating entity, bad things can happen. The typical use case when multiple threads are updated a database record is to throw a Concurrency exception to the user. Bad UX notwithstanding there are situations where this is not possible.

Imagine a Use Case where a server ‘process’ is processing large sets of data, and concurrency techniques where used to improve performance. In this scenario there are a few options when threads collide on an Entity; stop the process and go home, catch the exception and retry.

At times I feel the first option of stopping the process and going home is the best…

The second option of catching the exception and retrying can introduce more complicated issues. For example; if there were 5 threads updating an Entity, one thread will win and 4 will get the exception and be forced to retry. In some rare cases there might be a scenario where two threads deadlock on trying to access the Entity.

Another solution to this problem is to have all ‘work’ on an Entity be done synchronously. This trick is for this solution is to have a Thread Safe Queue in which we can en-queue work for an Entity and have it processed in order.

MailboxProcessor

MSDN Doc

The MailboxProcessor otherwise known as an 'Agent' is a nice abstraction over a queue. The Agent allows different threads to post items into an the queue and using F# Async Workflows each item is processed synchronously.

With ‘Agents' the construction of a solution is fairly straightforward. In the code block below I have constructed a class which will accept an Id for an Entity and an ‘Action’. For each Entity it will process each ‘Action’ in sequence.

Below is a review of the code block.

Line 11

There is an ‘Agent’ controls access to the Dictionary of Agents. This will insure that only one thread with be adding/reading from the dictionary at a time.

Line 19

So for each Entity there will be an Agent controlling the synchronous execution of ‘Action’. We can do this for decent number of Entities as the Agents do not require a lot of resources.

F# Code Block

1: open System 2: open System . Collections . Generic 3: 4: type internal AggregateAction = 5: { 6: Id : Guid 7: Action : Action 8: } 9: 10: type AggregateAgent () = 11: let agent = MailboxProcessor < AggregateAction > . Start ( fun inbox -> 12: let dic = new Dictionary < Guid , MailboxProcessor < Action > > () 13: async { 14: while true do 15: let! msg = inbox . Receive () 16: if dic . ContainsKey ( msg . Id ) then 17: dic . Item ( msg . Id ) . Post msg . Action 18: else 19: let aggAgent = MailboxProcessor < Action > . Start ( fun inbox -> 20: async { 21: while true do 22: let! action = inbox . Receive () 23: action . Invoke () |> ignore 24: }) 25: aggAgent . Post msg . Action 26: dic . Add ( msg . Id , aggAgent ) 27: }) 28: 29: member this . Process id action = 30: agent . Post { Id = id ; Action = action } 31:

namespace System

namespace System.Collections

namespace System.Collections.Generic

type internal AggregateAction =

{Id: Guid;

Action: Action;}



Full name: Snippet.AggregateAction



type: AggregateAction

implements: IEquatable<AggregateAction>

implements: Collections.IStructuralEquatable

AggregateAction.Id: Guid

type Guid =

struct

new : System.Byte [] -> System.Guid

new : uint32 * uint16 * uint16 * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte -> System.Guid

new : int * int16 * int16 * System.Byte [] -> System.Guid

new : int * int16 * int16 * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte * System.Byte -> System.Guid

new : string -> System.Guid

member CompareTo : obj -> int

member CompareTo : System.Guid -> int

member Equals : obj -> bool

member Equals : System.Guid -> bool

member GetHashCode : unit -> int

member ToByteArray : unit -> System.Byte []

member ToString : unit -> string

member ToString : string -> string

member ToString : string * System.IFormatProvider -> string

static val Empty : System.Guid

static member NewGuid : unit -> System.Guid

static member Parse : string -> System.Guid

static member ParseExact : string * string -> System.Guid

static member TryParse : string * System.Guid -> bool

static member TryParseExact : string * string * System.Guid -> bool

end



Full name: System.Guid



type: Guid

implements: IFormattable

implements: IComparable

implements: IComparable<Guid>

implements: IEquatable<Guid>

inherits: ValueType

Multiple items

AggregateAction.Action: Action



--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> unit



Full name: System.Action<_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> unit



Full name: System.Action<_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> unit



Full name: System.Action<_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 -> unit



Full name: System.Action<_,_,_,_>



type: Action<'T1,'T2,'T3,'T4>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3> =

delegate of 'T1 * 'T2 * 'T3 -> unit



Full name: System.Action<_,_,_>



type: Action<'T1,'T2,'T3>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2> =

delegate of 'T1 * 'T2 -> unit



Full name: System.Action<_,_>



type: Action<'T1,'T2>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T> =

delegate of 'T -> unit



Full name: System.Action<_>



type: Action<'T>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action =

delegate of unit -> unit



Full name: System.Action



type: Action

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> 'T16 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> unit)



--------------------



Action('T1 -> 'T2 -> unit)



--------------------



Action('T -> unit)



--------------------



Action(unit -> unit)

type AggregateAgent =

class

new : unit -> AggregateAgent

member Process : id:Guid -> action:Action -> unit

end



Full name: Snippet.AggregateAgent

val agent : MailboxProcessor<AggregateAction>



type: MailboxProcessor<AggregateAction>

implements: IDisposable

type MailboxProcessor<'Msg> =

class

interface IDisposable

new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:Threading.CancellationToken -> MailboxProcessor<'Msg>

member Post : message:'Msg -> unit

member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>

member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply

member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>

member Receive : ?timeout:int -> Async<'Msg>

member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>

member Start : unit -> unit

member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option

member TryReceive : ?timeout:int -> Async<'Msg option>

member TryScan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T option>

member add_Error : Handler<Exception> -> unit

member CurrentQueueLength : int

member DefaultTimeout : int

member Error : IEvent<Exception>

member remove_Error : Handler<Exception> -> unit

member DefaultTimeout : int with set

static member Start : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:Threading.CancellationToken -> MailboxProcessor<'Msg>

end



Full name: Microsoft.FSharp.Control.MailboxProcessor<_>



type: MailboxProcessor<'Msg>

implements: IDisposable

val inbox : MailboxProcessor<AggregateAction>



type: MailboxProcessor<AggregateAction>

implements: IDisposable

val dic : Dictionary<Guid,MailboxProcessor<Action>>



type: Dictionary<Guid,MailboxProcessor<Action>>

implements: IDictionary<Guid,MailboxProcessor<Action>>

implements: ICollection<KeyValuePair<Guid,MailboxProcessor<Action>>>

implements: seq<KeyValuePair<Guid,MailboxProcessor<Action>>>

implements: Collections.IDictionary

implements: Collections.ICollection

implements: Collections.IEnumerable

implements: Runtime.Serialization.ISerializable

implements: Runtime.Serialization.IDeserializationCallback

type Dictionary<'TKey,'TValue> =

class

new : unit -> System.Collections.Generic.Dictionary<'TKey,'TValue>

new : int -> System.Collections.Generic.Dictionary<'TKey,'TValue>

new : System.Collections.Generic.IEqualityComparer<'TKey> -> System.Collections.Generic.Dictionary<'TKey,'TValue>

new : int * System.Collections.Generic.IEqualityComparer<'TKey> -> System.Collections.Generic.Dictionary<'TKey,'TValue>

new : System.Collections.Generic.IDictionary<'TKey,'TValue> -> System.Collections.Generic.Dictionary<'TKey,'TValue>

new : System.Collections.Generic.IDictionary<'TKey,'TValue> * System.Collections.Generic.IEqualityComparer<'TKey> -> System.Collections.Generic.Dictionary<'TKey,'TValue>

member Add : 'TKey * 'TValue -> unit

member Clear : unit -> unit

member Comparer : System.Collections.Generic.IEqualityComparer<'TKey>

member ContainsKey : 'TKey -> bool

member ContainsValue : 'TValue -> bool

member Count : int

member GetEnumerator : unit -> Enumerator<'TKey,'TValue>

member GetObjectData : System.Runtime.Serialization.SerializationInfo * System.Runtime.Serialization.StreamingContext -> unit

member Item : 'TKey -> 'TValue with get, set

member Keys : KeyCollection<'TKey,'TValue>

member OnDeserialization : obj -> unit

member Remove : 'TKey -> bool

member TryGetValue : 'TKey * 'TValue -> bool

member Values : ValueCollection<'TKey,'TValue>

type Enumerator =

struct

member Current : System.Collections.Generic.KeyValuePair<'TKey,'TValue>

member Dispose : unit -> unit

member MoveNext : unit -> bool

end

type KeyCollection =

class

new : System.Collections.Generic.Dictionary<'TKey,'TValue> -> KeyCollection

member CopyTo : 'TKey [] * int -> unit

member Count : int

member GetEnumerator : unit -> Enumerator<'TKey,'TValue>

type Enumerator =

struct

member Current : 'TKey

member Dispose : unit -> unit

member MoveNext : unit -> bool

end

end

type ValueCollection =

class

new : System.Collections.Generic.Dictionary<'TKey,'TValue> -> ValueCollection

member CopyTo : 'TValue [] * int -> unit

member Count : int

member GetEnumerator : unit -> Enumerator<'TKey,'TValue>

type Enumerator =

struct

member Current : 'TValue

member Dispose : unit -> unit

member MoveNext : unit -> bool

end

end

end



Full name: System.Collections.Generic.Dictionary<_,_>



type: Dictionary<'TKey,'TValue>

implements: IDictionary<'TKey,'TValue>

implements: ICollection<KeyValuePair<'TKey,'TValue>>

implements: seq<KeyValuePair<'TKey,'TValue>>

implements: Collections.IDictionary

implements: Collections.ICollection

implements: Collections.IEnumerable

implements: Runtime.Serialization.ISerializable

implements: Runtime.Serialization.IDeserializationCallback

Multiple items

type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 * 'T16 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15,'T16>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 * 'T15 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14,'T15>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 * 'T14 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13,'T14>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 * 'T13 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12,'T13>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 * 'T12 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11,'T12>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 * 'T11 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10,'T11>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 * 'T10 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9,'T10>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 * 'T9 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8,'T9>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8 -> unit



Full name: System.Action<_,_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7,'T8>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 -> unit



Full name: System.Action<_,_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6,'T7>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5,'T6> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 -> unit



Full name: System.Action<_,_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5,'T6>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4,'T5> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 * 'T5 -> unit



Full name: System.Action<_,_,_,_,_>



type: Action<'T1,'T2,'T3,'T4,'T5>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3,'T4> =

delegate of 'T1 * 'T2 * 'T3 * 'T4 -> unit



Full name: System.Action<_,_,_,_>



type: Action<'T1,'T2,'T3,'T4>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2,'T3> =

delegate of 'T1 * 'T2 * 'T3 -> unit



Full name: System.Action<_,_,_>



type: Action<'T1,'T2,'T3>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T1,'T2> =

delegate of 'T1 * 'T2 -> unit



Full name: System.Action<_,_>



type: Action<'T1,'T2>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action<'T> =

delegate of 'T -> unit



Full name: System.Action<_>



type: Action<'T>

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



type Action =

delegate of unit -> unit



Full name: System.Action



type: Action

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate





--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> 'T16 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> 'T15 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> 'T14 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> 'T13 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> 'T12 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> 'T11 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> 'T10 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> 'T9 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> 'T8 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> 'T7 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> 'T6 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> 'T5 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> 'T4 -> unit)



--------------------



Action('T1 -> 'T2 -> 'T3 -> unit)



--------------------



Action('T1 -> 'T2 -> unit)



--------------------



Action('T -> unit)



--------------------



Action(unit -> unit)

val async : AsyncBuilder



Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async

val msg : AggregateAction



type: AggregateAction

implements: IEquatable<AggregateAction>

implements: Collections.IStructuralEquatable

member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>

Dictionary.ContainsKey(key: Guid) : bool

property Dictionary.Item: Guid -> MailboxProcessor<Action>

val aggAgent : MailboxProcessor<Action>



type: MailboxProcessor<Action>

implements: IDisposable

val inbox : MailboxProcessor<Action>



type: MailboxProcessor<Action>

implements: IDisposable

val action : Action



type: Action

implements: ICloneable

implements: Runtime.Serialization.ISerializable

inherits: MulticastDelegate

inherits: Delegate

val ignore : 'T -> unit



Full name: Microsoft.FSharp.Core.Operators.ignore

member MailboxProcessor.Post : message:'Msg -> unit

AggregateAction.Action: Action

Dictionary.Add(key: Guid, value: MailboxProcessor<Action>) : unit

val this : AggregateAgent

member AggregateAgent.Process : id:Guid -> action:Action -> unit



Full name: Snippet.AggregateAgent.Process

val id : Guid



type: Guid

implements: IFormattable

implements: IComparable

implements: IComparable<Guid>

implements: IEquatable<Guid>

inherits: ValueType

One thing to note, each ‘Action’ type being processed should handle any errors it encounters as the Aggregate Agent will not know how to proceed.