Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Crea un cálculo asincrónico en relación con 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 aplicación de servidor simple que acepta una conexión, recibe datos de un servidor, y envía una respuesta.
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)
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 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()
Resultados del ejemplo
Plataformas
Windows 7, Windows Vista SP2, Windows XP SP3, Windows XP x64 SP2, Windows Server 2008 R2, Windows Server 2008 SP2, Windows Server 2003 SP2
Información de versiones
Runtime de F#
Se admite en las versiones: 2.0, 4.0
Silverlight
Se admite en la versión: 3
Vea también
Referencia
Microsoft.FSharp.Control (Espacio de nombres de F#)
Historial de cambios
Fecha |
Historial |
Motivo |
|---|---|---|
|
Julio de 2010 |
Se han agregado ejemplos de código. |
Mejora de la información. |