Async.FromBeginEnd<'T> 메서드(F#)
업데이트: 2010년 7월
작업의 시작/종료 쌍과 관련된 비동기 계산을 CLI API에 사용되는 스타일로 만듭니다.
네임스페이스/모듈 경로: Microsoft.FSharp.Control
어셈블리: FSharp.Core(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)
매개 변수
beginAction
형식: AsyncCallback * obj -> IAsyncResult일반적인 CLI 비동기 연산을 시작하는 함수입니다.
endAction
형식: IAsyncResult -> 'T일반적인 CLI 비동기 연산을 완료하는 함수입니다.
cancelAction
형식: (unit -> unit)취소가 요청될 때 실행되는 선택적 함수입니다.
반환 값
지정된 시작/종료 함수를 래핑하는 비동기 계산입니다.
설명
예를 들어, 다음 코드는 웹 서비스 호출을 래핑하는 비동기 계산을 만듭니다.
Async.FromBeginEnd(ws.BeginGetWeather,ws.EndGetWeather)
계산을 실행하면 계산이 계속됨을 나타내는 콜백과 함께 beginFunc가 실행됩니다. 콜백을 호출하면 endFunc를 사용하여 전체 결과가 페치됩니다.
이 계산은 연산이 완료될 때까지 대기하는 동안 취소에 응답합니다. 취소가 발생할 경우 cancelAction이 지정되어 있으면 이 작업이 실행되고 계산은 연산이 완료될 때까지 계속 대기합니다. cancelAction이 지정되어 있지 않은 경우 취소가 발생하면 계산이 즉시 중지되고 이후의 콜백 호출은 무시됩니다.
예제
다음 코드 예제에는 시작/종료 패턴을 사용하는 .NET 비동기 API에서 F# 비동기 계산을 생성하는 방법에 대해 보여줍니다. 이 예제에서는 System.Net.Sockets에 .NET 소켓 API를 사용합니다. 연결이 가능하고 서버로부터 데이터를 수신하며 응답을 보내는 간단한 서버 응용 프로그램의 구현입니다.
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)
다음 코드 예제에서는 이전 예제에서 서버 코드와 함께 사용할 수 있는 클라이언트 코드를 보여줍니다.
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()
샘플 출력
플랫폼
Windows 7, Windows Vista SP2, Windows XP SP3, Windows XP x64 SP2, Windows Server 2008 R2, Windows Server 2008 SP2, Windows Server 2003 SP2
버전 정보
F# 런타임
지원되는 버전: 2.0, 4.0
Silverlight
지원되는 버전: 3
참고 항목
참조
Microsoft.FSharp.Control 네임스페이스(F#)
변경 기록
날짜 |
변경 내용 |
이유 |
---|---|---|
2010년 7월 |
코드 예제를 추가했습니다. |
향상된 기능 관련 정보 |