Я медленно изучал все функции, которые F # приносит в таблицу. Меня особенно заинтересовал MailboxProcessor
.Является ли MailboxProcessor заменой для блокировок?
- Эквивалент этого в C#, скорее всего, будет использовать блокировки. Можно ли считать
MailboxProcessor
заменой замков? - В следующем примере я делаю что-нибудь особенно наивное или может вы видите что-нибудь, что может быть улучшено?
module Tcp =
open System
open System.Collections.Generic
open System.Net
open System.Net.Sockets
open System.Threading
type SocketAsyncMessage =
| Get of AsyncReplyChannel<SocketAsyncEventArgs>
| Put of SocketAsyncEventArgs
| Dispose of AsyncReplyChannel<MailboxProcessor<SocketAsyncMessage>>
type SocketAsyncEventArgsPool(size:int) =
let agent =
lazy(MailboxProcessor.Start(
(fun inbox ->
let references = lazy(new List<SocketAsyncEventArgs>(size))
let idleReferences = lazy(new Queue<SocketAsyncEventArgs>(size))
let rec loop() =
async {
let! message = inbox.Receive()
match message with
| Get channel ->
if idleReferences.Value.Count > 0 then
channel.Reply(idleReferences.Value.Dequeue())
else
let args = new SocketAsyncEventArgs()
references.Value.Add args
channel.Reply args
return! loop()
| Put args ->
if args = null then
nullArg "args"
elif references.Value.Count < size then
idleReferences.Value.Enqueue args
else
if not(references.Value.Remove args) then
invalidOp "Reference not found."
args.Dispose()
return! loop()
| Dispose channel ->
if references.IsValueCreated then
references.Value
|> Seq.iter(fun args -> args.Dispose())
channel.Reply inbox
}
loop())))
/// Returns a SocketAsyncEventArgs instance from the pool.
member this.Get() =
agent.Value.PostAndReply(fun channel -> Get channel)
/// Returns the SocketAsyncEventArgs instance to the pool.
member this.Put args =
agent.Value.Post(Put args)
/// Releases all resources used by the SocketAsyncEventArgsPool.
member this.Dispose() =
(this:>IDisposable).Dispose()
interface IDisposable with
member this.Dispose() =
if agent.IsValueCreated then
(agent.Value.PostAndReply(fun channel -> Dispose channel):>IDisposable).Dispose()
Вы знаете, что абсолютно правы. У меня нет причин ждать объекта args, когда я могу передать функцию. Функции, которые нуждаются в объекте args, в любом случае являются асинхронными. – ChaosPandion