Share via


Async.FromBeginEnd<'T>-Methode (F#)

Erstellt eine asynchrone Berechnung mit paarweisen Begin/End-Aktionen in dem Format, das in CLI-APIs verwendet wird.

Namespace/Modulpfad: Microsoft.FSharp.Control

Assembly: FSharp.Core (in 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)

Parameter

  • beginAction
    Typ: AsyncCallback * obj -> IAsyncResult

    Die Funktion, die einen herkömmlichen asynchronen CLI-Vorgang einleitet.

  • endAction
    Typ: IAsyncResult -> 'T

    Die Funktion, die einen herkömmlichen asynchronen CLI-Vorgang abschließt.

  • cancelAction
    Typ: (unit -> unit)

    Eine optionale Funktion, die ausgeführt wird, wenn ein Abbruch angefordert wird.

Rückgabewert

Eine asynchrone Berechnung, die die gegebenen Begin/End-Funktionen umschließt.

Hinweise

Beispielsweise erstellt der folgende Code eine asynchrone Berechnung, die einen Webdienstaufruf umschließt.

Async.FromBeginEnd(ws.BeginGetWeather,ws.EndGetWeather)

Wenn die Berechnung ausgeführt wird, wird beginFunc mit einem Rückruf ausgeführt, der die Fortsetzung der Berechnung darstellt. Beim Aufrufen des Rückrufs wird das Gesamtergebnis mit endFunc abgerufen.

Die Berechnung reagiert auf einen Abbruch, während sie auf den Abschluss der Operation wartet. Wenn ein Abbruch auftritt und cancelAction angegeben ist, wird diese Aktion ausgeführt, und die Berechnung wartet weiter auf den Abschluss der Operation. Wenn cancelAction nicht angegeben ist, dann führt das Auftreten eines Abbruchs zum sofortigen Ende der Berechnung. Nachfolgende Aufrufe des Rückrufs werden ignoriert.

Beispiel

Im folgenden Codebeispiel wird veranschaulicht, wie eine asynchrone F#-Berechnung aus einer asynchronen .NET-API erstellt wird, die auf dem Begin/End-Muster basiert. Im Beispiel wird die .NET-Socket API in System.Net.Sockets verwendet. Es handelt sich um eine Implementierung einer einfachen Serveranwendung, die eine Verbindung akzeptiert, Daten von einem Server empfängt und eine Antwort sendet.

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)
              

Im folgenden Codebeispiel wird der Clientcode dargestellt, der zusammen mit dem Servercode im vorherigen Beispiel verwendet werden kann.

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()

Beispielausgabe

            

Plattformen

Windows 7, Windows Vista SP2, Windows XP SP3, Windows XP x64 SP2, Windows Server 2008 R2, Windows Server 2008 SP2, Windows Server 2003 SP2

Versionsinformationen

F#-Runtime

Unterstützt in: 2.0, 4.0

Silverlight

Unterstützt in: 3

Siehe auch

Weitere Ressourcen

Control.Async-Klasse (F#)

Microsoft.FSharp.Control-Namespace (F#)

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Juli 2010

Codebeispiele hinzugefügt.

Informationsergänzung.