0 people like it.

F#-friendly SocketAsyncEventArgs

The name is a bit trying, but the overall callback approach greatly simplifies the mechanism for calling and handling the System.Net.Sockets.Socket Async methods.

An F#-friendly SocketAsyncEventArgs subclass

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
type AsyncSocketEventArgs(callback: SocketAsyncEventArgs -> unit) as x =
    inherit SocketAsyncEventArgs()
    let mutable disposed = false
    let subscription = x.Completed.Subscribe(callback)
    member private x.Dispose(disposing) =
        if not disposed then
            if disposing then
                subscription.Dispose()
            base.Dispose()
            disposed <- true
    member x.CallbackSync() = callback x
    /// Call Close when using AsyncSocketEventArgs and not Dispose,
    /// or cast to IDisposable to use the explicit implementation.
    /// This is necessary as the dispose method is sealed on the
    /// SocketAsyncEventArgs
    member x.Close() =
        x.Dispose(true)
    override x.Finalize() =
        x.Dispose(false)
    interface IDisposable with
        member x.Dispose() =
            x.Dispose(true)
            GC.SuppressFinalize(x)

Socket extensions using the AsyncSocketEventArgs type

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
/// Helper method to make Async calls easier.  InvokeAsyncMethod ensures the callback always
/// gets called even if an error occurs or the Async method completes synchronously.
let inline invokeAsyncMethod(asyncmethod, args:AsyncSocketEventArgs) =
    let result = asyncmethod args
    if result <> true then
        args.CallbackSync()

type Socket with 
    member s.AcceptAsync(args) =
        invokeAsyncMethod(s.AcceptAsync, args) 
    member s.ReceiveAsync(args) =
        invokeAsyncMethod(s.ReceiveAsync, args) 
    member s.SendAsync(args) =
        invokeAsyncMethod(s.SendAsync, args) 
    member s.ConnectAsync(args) =
        invokeAsyncMethod(s.ConnectAsync, args)
    member s.DisconnectAsync(args) =
        invokeAsyncMethod(s.DisconnectAsync, args)
Multiple items
type AsyncSocketEventArgs =
  inherit SocketAsyncEventArgs
  interface IDisposable
  new : callback:(SocketAsyncEventArgs -> unit) -> AsyncSocketEventArgs
  member CallbackSync : unit -> unit
  member Close : unit -> unit
  member private Dispose : disposing:bool -> unit
  override Finalize : unit -> unit

Full name: Script.AsyncSocketEventArgs


 An F#-friendly SocketAsyncEventArgs subclass.


--------------------
new : callback:(SocketAsyncEventArgs -> unit) -> AsyncSocketEventArgs
val callback : (SocketAsyncEventArgs -> unit)
Multiple items
type SocketAsyncEventArgs =
  inherit EventArgs
  new : unit -> SocketAsyncEventArgs
  member AcceptSocket : Socket with get, set
  member Buffer : byte[]
  member BufferList : IList<ArraySegment<byte>> with get, set
  member BytesTransferred : int
  member ConnectByNameError : Exception
  member ConnectSocket : Socket
  member Count : int
  member DisconnectReuseSocket : bool with get, set
  member Dispose : unit -> unit
  ...

Full name: System.Net.Sockets.SocketAsyncEventArgs

--------------------
SocketAsyncEventArgs() : unit
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val x : AsyncSocketEventArgs
val mutable disposed : bool
val subscription : IDisposable
event SocketAsyncEventArgs.Completed: IEvent<EventHandler<SocketAsyncEventArgs>,SocketAsyncEventArgs>
member IObservable.Subscribe : callback:('T -> unit) -> IDisposable
IObservable.Subscribe(observer: IObserver<SocketAsyncEventArgs>) : IDisposable
member private AsyncSocketEventArgs.Dispose : disposing:bool -> unit

Full name: Script.AsyncSocketEventArgs.Dispose
val disposing : bool
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
IDisposable.Dispose() : unit
member AsyncSocketEventArgs.CallbackSync : unit -> unit

Full name: Script.AsyncSocketEventArgs.CallbackSync
member AsyncSocketEventArgs.Close : unit -> unit

Full name: Script.AsyncSocketEventArgs.Close


 Call Close when using AsyncSocketEventArgs and not Dispose,
 or cast to IDisposable to use the explicit implementation.
 This is necessary as the dispose method is sealed on the
 SocketAsyncEventArgs
SocketAsyncEventArgs.Dispose() : unit
member private AsyncSocketEventArgs.Dispose : disposing:bool -> unit
override AsyncSocketEventArgs.Finalize : unit -> unit

Full name: Script.AsyncSocketEventArgs.Finalize
type IDisposable =
  member Dispose : unit -> unit

Full name: System.IDisposable
override AsyncSocketEventArgs.Dispose : unit -> unit

Full name: Script.AsyncSocketEventArgs.Dispose
type GC =
  static member AddMemoryPressure : bytesAllocated:int64 -> unit
  static member CancelFullGCNotification : unit -> unit
  static member Collect : unit -> unit + 2 overloads
  static member CollectionCount : generation:int -> int
  static member GetGeneration : obj:obj -> int + 1 overload
  static member GetTotalMemory : forceFullCollection:bool -> int64
  static member KeepAlive : obj:obj -> unit
  static member MaxGeneration : int
  static member ReRegisterForFinalize : obj:obj -> unit
  static member RegisterForFullGCNotification : maxGenerationThreshold:int * largeObjectHeapThreshold:int -> unit
  ...

Full name: System.GC
GC.SuppressFinalize(obj: obj) : unit
val invokeAsyncMethod : asyncmethod:(AsyncSocketEventArgs -> bool) * args:AsyncSocketEventArgs -> unit

Full name: Script.invokeAsyncMethod


 Helper method to make Async calls easier. InvokeAsyncMethod ensures the callback always
 gets called even if an error occurs or the Async method completes synchronously.
val asyncmethod : (AsyncSocketEventArgs -> bool)
val args : AsyncSocketEventArgs
val result : bool
member AsyncSocketEventArgs.CallbackSync : unit -> unit
Multiple items
type Socket =
  new : socketInformation:SocketInformation -> Socket + 1 overload
  member Accept : unit -> Socket
  member AcceptAsync : e:SocketAsyncEventArgs -> bool
  member AddressFamily : AddressFamily
  member Available : int
  member BeginAccept : callback:AsyncCallback * state:obj -> IAsyncResult + 2 overloads
  member BeginConnect : remoteEP:EndPoint * callback:AsyncCallback * state:obj -> IAsyncResult + 3 overloads
  member BeginDisconnect : reuseSocket:bool * callback:AsyncCallback * state:obj -> IAsyncResult
  member BeginReceive : buffers:IList<ArraySegment<byte>> * socketFlags:SocketFlags * callback:AsyncCallback * state:obj -> IAsyncResult + 3 overloads
  member BeginReceiveFrom : buffer:byte[] * offset:int * size:int * socketFlags:SocketFlags * remoteEP:EndPoint * callback:AsyncCallback * state:obj -> IAsyncResult
  ...

Full name: System.Net.Sockets.Socket

--------------------
Socket(socketInformation: SocketInformation) : unit
Socket(addressFamily: AddressFamily, socketType: SocketType, protocolType: ProtocolType) : unit
val s : Socket
member Socket.AcceptAsync : args:AsyncSocketEventArgs -> unit

Full name: Script.AcceptAsync
member Socket.AcceptAsync : args:AsyncSocketEventArgs -> unit
Socket.AcceptAsync(e: SocketAsyncEventArgs) : bool
member Socket.ReceiveAsync : args:AsyncSocketEventArgs -> unit

Full name: Script.ReceiveAsync
member Socket.ReceiveAsync : args:AsyncSocketEventArgs -> unit
Socket.ReceiveAsync(e: SocketAsyncEventArgs) : bool
member Socket.SendAsync : args:AsyncSocketEventArgs -> unit

Full name: Script.SendAsync
member Socket.SendAsync : args:AsyncSocketEventArgs -> unit
Socket.SendAsync(e: SocketAsyncEventArgs) : bool
member Socket.ConnectAsync : args:AsyncSocketEventArgs -> unit

Full name: Script.ConnectAsync
member Socket.ConnectAsync : args:AsyncSocketEventArgs -> unit
Socket.ConnectAsync(e: SocketAsyncEventArgs) : bool
member Socket.DisconnectAsync : args:AsyncSocketEventArgs -> unit

Full name: Script.DisconnectAsync
member Socket.DisconnectAsync : args:AsyncSocketEventArgs -> unit
Socket.DisconnectAsync(e: SocketAsyncEventArgs) : bool

More information

Link:http://fssnip.net/8L
Posted:6 years ago
Author:Ryan Riley
Tags: network , sockets , fracture , async , socketasynceventargs