Async.FromBeginEnd<'T> (Método de F#)
Crea un cálculo asincrónico en términos de un par de acciones Begin/End con el estilo usado en las API de CLI.
Espacio de nombres/Ruta de acceso del módulo: Microsoft.FSharp.Control
Ensamblado: FSharp.Core (en FSharp.Core.dll)
// Signature:
static member FromBeginEnd : (AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * ?(unit -> unit) -> Async<'T>
// Usage:
Async.FromBeginEnd (beginAction, endAction)
Async.FromBeginEnd (beginAction, endAction, cancelAction = cancelAction)
Parámetros
beginAction
Tipo: AsyncCallback * obj -> IAsyncResultFunción que inicia una operación asincrónica tradicional de CLI.
endAction
Tipo: IAsyncResult -> 'TFunción que completa una operación asincrónica tradicional de CLI.
cancelAction
Tipo: (unit -> unit)Función opcional que se ejecuta cuando se solicita una cancelación.
Valor devuelto
Cálculo asincrónico que encapsula las funciones Begin/End especificadas.
Comentarios
Por ejemplo, el código siguiente crea un cálculo asincrónico que encapsula una llamada al servicio Web.
Async.FromBeginEnd(ws.BeginGetWeather,ws.EndGetWeather)
Cuando se ejecuta el cálculo, se ejecuta beginFunc, con una devolución de llamada que representa la continuación del cálculo. Cuando se invoca la devolución de llamada, se captura el resultado general mediante endFunc.
El cálculo responderá a la cancelación mientras espera a que se complete la operación. Si se produce una cancelación y se ha especificado cancelAction, se ejecuta y el cálculo continúa esperando a que se complete la operación. Si no se especifica cancelAction, la cancelación hace que el cálculo se detenga inmediatamente y se invalidan las siguientes invocaciones de la devolución de llamada.
Ejemplo
En el ejemplo de código siguiente se muestra cómo crear un cálculo asincrónico de F# a partir de una API asincrónica de .NET que use el patrón Begin/End. En el ejemplo se usa la API de sockets de .NET en System.Net.Sockets. Es una implementación de una sencilla aplicación de servidor que acepta una conexión, recibe los datos de un cliente, y enviar una respuesta.
module SocketServer =
open System.Net
open System.Net.Sockets
open System.Collections.Generic
let toIList<'T> (data : 'T array) =
let segment = new System.ArraySegment<'T>(data)
let data = new List<System.ArraySegment<'T>>() :> IList<System.ArraySegment<'T>>
data.Add(segment)
data
type Socket with
member this.MyAcceptAsync() =
Async.FromBeginEnd((fun (callback, state) -> this.BeginAccept(callback, state)),
this.EndAccept)
member this.MyConnectAsync(ipAddress : IPAddress, port : int) =
Async.FromBeginEnd(ipAddress, port,
(fun (ipAddress:IPAddress, port, callback, state) ->
this.BeginConnect(ipAddress, port, callback, state)),
this.EndConnect)
member this.MySendAsync(data : byte array, flags : SocketFlags) =
Async.FromBeginEnd(toIList data, flags,
(fun (data : IList<System.ArraySegment<byte>>,
flags : SocketFlags, callback, state) ->
this.BeginSend(data, flags, callback, state)),
this.EndSend)
member this.MyReceiveAsync(data : byte array, flags : SocketFlags) =
Async.FromBeginEnd(toIList data, flags,
(fun (data : IList<System.ArraySegment<byte>>,
flags : SocketFlags, callback, state) ->
this.BeginReceive(data, flags, callback, state)),
this.EndReceive)
let port = 11000
let socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
let ipHostInfo = Dns.Resolve(Dns.GetHostName())
let localIPAddress = ipHostInfo.AddressList.[0]
let localEndPoint = new IPEndPoint(localIPAddress, port)
socket.Bind(localEndPoint)
let connectSendReceive (socket : Socket) =
async {
do! socket.MyConnectAsync(ipHostInfo.AddressList.[0], 11000)
let buffer1 = [| 0uy .. 255uy |]
let buffer2 = Array.zeroCreate<byte> 255
let flags = new SocketFlags()
let! flag = socket.MySendAsync(buffer1, flags)
let! result = socket.MyReceiveAsync(buffer2, flags)
return buffer2
}
let acceptReceiveSend (socket : Socket) =
async {
printfn "Listening..."
socket.Listen(10)
printfn "Accepting..."
let! socket = socket.MyAcceptAsync()
let buffer1 = Array.zeroCreate<byte> 256
let flags = new SocketFlags()
printfn "Receiving..."
let! nBytes = socket.MyReceiveAsync(buffer1, flags)
printfn "Received %d bytes from client computer." nBytes
let buffer2 = Array.rev buffer1
printfn "Sending..."
let! flag = socket.MySendAsync(buffer2, flags)
printfn "Completed."
return buffer2
}
let taskServer = Async.StartAsTask(acceptReceiveSend(socket))
taskServer.Wait()
socket.Close()
Output
En el ejemplo de código siguiente se muestra el código de cliente que se puede usar junto con el código del servidor en el ejemplo anterior.
module SocketClient =
open System.Net
open System.Net.Sockets
open System.Collections.Generic
let toIList<'T> (data : 'T array) =
let segment = new System.ArraySegment<'T>(data)
let data = new List<System.ArraySegment<'T>>() :> IList<System.ArraySegment<'T>>
data.Add(segment)
data
type Socket with
member this.MyAcceptAsync(receiveSize) =
Async.FromBeginEnd(receiveSize,
(fun (receiveSize, callback, state) ->
this.BeginAccept(receiveSize, callback, state)),
this.EndConnect)
member this.MyConnectAsync(ipAddress : IPAddress, port : int) =
Async.FromBeginEnd(ipAddress, port,
(fun (ipAddress:IPAddress, port, callback, state) ->
this.BeginConnect(ipAddress, port, callback, state)),
this.EndConnect)
member this.MySendAsync(data, flags : SocketFlags) =
Async.FromBeginEnd(toIList data, flags,
(fun (data : IList<System.ArraySegment<byte>>,
flags : SocketFlags, callback, state) ->
this.BeginSend(data, flags, callback, state)),
this.EndSend)
member this.MyReceiveAsync(data, flags : SocketFlags) =
Async.FromBeginEnd(toIList data, flags,
(fun (data : IList<System.ArraySegment<byte>>,
flags : SocketFlags, callback, state) ->
this.BeginReceive(data, flags, callback, state)),
this.EndReceive)
let port = 11000
let socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
let ipHostEntry = Dns.Resolve("hostname.contoso.com")
printfn "Server address: %s" (ipHostEntry.AddressList.[0].ToString())
let connectSendReceive (socket : Socket) =
async {
do! socket.MyConnectAsync(ipHostEntry.AddressList.[0], 11000)
printfn "Connected to remote host."
let buffer1 = [| 0uy .. 255uy |]
let buffer2 = Array.zeroCreate<byte> 255
let flags = new SocketFlags()
printfn "Sending data..."
let! flag = socket.MySendAsync(buffer1, flags)
printfn "Receiving data..."
let! result = socket.MyReceiveAsync(buffer2, flags)
printfn "Received data from remote host."
return buffer2
}
let acceptReceiveSend (socket : Socket) =
async {
socket.Listen(1)
do! socket.MyAcceptAsync(256)
let buffer1 = Array.zeroCreate<byte> 255
let flags = new SocketFlags()
let! flag = socket.MyReceiveAsync(buffer1, flags)
let buffer2 = Array.rev buffer1
let! flag = socket.MySendAsync(buffer2, flags)
return buffer2
}
let taskClient = Async.StartAsTask(connectSendReceive(socket))
taskClient.Wait()
taskClient.Result |> Array.iter (fun elem -> printf "%d " elem)
Resultados del ejemplo
Plataformas
Windows 8, Windows 7, Windows Server 2012, Windows Server 2008 R2
Información de versiones
Versiones de la biblioteca básica de F#
Se admite en: 2.0, 4.0, portables