비동기 워크플로Asynchronous Workflows

참고

API 참조 링크를 통해 MSDN으로 이동됩니다.The API reference link will take you to MSDN. docs.microsoft.com API 참조가 완전하지 않습니다.The docs.microsoft.com API reference is not complete.

이 항목에서는 다른 작업 F# 의 실행을 차단 하지 않고 비동기적으로 계산을 수행 하기 위한의 지원에 대해 설명 합니다.This topic describes support in F# for performing computations asynchronously, that is, without blocking execution of other work. 예를 들어 비동기 계산은 응용 프로그램에서 다른 작업을 수행할 때 사용자에 게 응답성이 유지 되는 Ui가 있는 응용 프로그램을 작성 하는 데 사용할 수 있습니다.For example, asynchronous computations can be used to write applications that have UIs that remain responsive to users as the application performs other work.

구문Syntax

async { expression }

설명Remarks

이전 구문에서로 expression 표시 되는 계산은 비동기 절전 모드 작업, i/o 및 기타 비동기 작업을 수행할 때 현재 계산 스레드를 차단 하지 않고 비동기적으로 실행 되도록 설정 됩니다.In the previous syntax, the computation represented by expression is set up to run asynchronously, that is, without blocking the current computation thread when asynchronous sleep operations, I/O, and other asynchronous operations are performed. 비동기 계산은 종종 현재 스레드에서 실행을 계속 하는 동안 백그라운드 스레드에서 시작 됩니다.Asynchronous computations are often started on a background thread while execution continues on the current thread. 식의 형식은입니다 Async<'T>. 여기서 'Treturn 키워드가 사용 될 때 식에서 반환 되는 형식입니다.The type of the expression is Async<'T>, where 'T is the type returned by the expression when the return keyword is used. 이러한 식의 코드는 비동기블록 또는 비동기 블록이라고 합니다.The code in such an expression is referred to as an asynchronous block, or async block.

프로그래밍에는 여러 가지 방법이 있으며, 클래스는 Async 여러 시나리오를 지 원하는 메서드를 제공 합니다.There are a variety of ways of programming asynchronously, and the Async class provides methods that support several scenarios. 일반적인 방법은 비동기 방식으로 실행 Async 하려는 계산 또는 계산을 나타내는 개체를 만든 다음 트리거 함수 중 하나를 사용 하 여 이러한 계산을 시작 하는 것입니다.The general approach is to create Async objects that represent the computation or computations that you want to run asynchronously, and then start these computations by using one of the triggering functions. 여러 트리거 함수는 비동기 계산을 실행 하는 다양 한 방법을 제공 하 고, 사용 하는 함수는 현재 스레드, 백그라운드 스레드 또는 .NET Framework 작업 개체 중 어떤 것을 사용할지 여부 및 연속이 있는지 여부에 따라 달라 집니다. 계산이 완료 될 때 실행 되어야 하는 함수입니다.The various triggering functions provide different ways of running asynchronous computations, and which one you use depends on whether you want to use the current thread, a background thread, or a .NET Framework task object, and whether there are continuation functions that should run when the computation finishes. 예를 들어 현재 스레드에서 비동기 계산을 시작 하려면를 사용할 Async.StartImmediate수 있습니다.For example, to start an asynchronous computation on the current thread, you can use Async.StartImmediate. UI 스레드에서 비동기 계산을 시작할 때 키 입력 및 마우스 작업과 같은 사용자 동작을 처리 하는 주 이벤트 루프를 차단 하지 않으므로 응용 프로그램의 응답성이 향상 됩니다.When you start an asynchronous computation from the UI thread, you do not block the main event loop that processes user actions such as keystrokes and mouse activity, so your application remains responsive.

Let을 사용 하 여 비동기 바인딩Asynchronous Binding by Using let!

비동기 워크플로에서 일부 식과 작업은 동기적으로 수행 되며, 일부는 비동기 결과를 반환 하도록 디자인 된 계산 보다 깁니다.In an asynchronous workflow, some expressions and operations are synchronous, and some are longer computations that are designed to return a result asynchronously. 일반 let 바인딩 대신 비동기 방식으로 메서드를 호출 하는 경우에는를 let!사용 합니다.When you call a method asynchronously, instead of an ordinary let binding, you use let!. let! 효과는 계산이 수행 되는 동안 다른 계산 또는 스레드에서 실행을 계속할 수 있도록 하는 것입니다.The effect of let! is to enable execution to continue on other computations or threads as the computation is being performed. let! 바인딩의 오른쪽이 반환 된 후 비동기 워크플로의 나머지 부분이 실행을 다시 시작 합니다.After the right side of the let! binding returns, the rest of the asynchronous workflow resumes execution.

다음 코드에서는 letlet!의 차이점을 보여 줍니다.The following code shows the difference between let and let!. 를 사용 하는 let 코드 줄은 나중에 Async.StartImmediate 또는 Async.RunSynchronously와 같이를 사용 하 여 나중에 실행할 수 있는 개체로 비동기 계산을 만듭니다.The line of code that uses let just creates an asynchronous computation as an object that you can run later by using, for example, Async.StartImmediate or Async.RunSynchronously. 에서 사용 let! 하는 코드 줄은 계산을 시작 하 고, 결과를 사용할 수 있을 때까지 스레드를 일시 중단 하 여 지점 실행이 계속 됩니다.The line of code that uses let! starts the computation, and then the thread is suspended until the result is available, at which point execution continues.

// let just stores the result as an asynchronous operation.
let (result1 : Async<byte[]>) = stream.AsyncRead(bufferSize)
// let! completes the asynchronous operation and returns the data.
let! (result2 : byte[])  = stream.AsyncRead(bufferSize)

let!에도를 사용 use! 하 여 비동기 바인딩을 수행할 수 있습니다.In addition to let!, you can use use! to perform asynchronous bindings. let! 간의use! 차이는 let 와 의차이와동일합니다.useThe difference between let! and use! is the same as the difference between let and use. use!경우 개체는 현재 범위를 닫을 때 삭제 됩니다.For use!, the object is disposed of at the close of the current scope. F# 언어use! 의 현재 릴리스에서는 use 가 인 경우에도 값을 null로 초기화 하는 것을 허용 하지 않습니다.Note that in the current release of the F# language, use! does not allow a value to be initialized to null, even though use does.

비동기 기본 형식Asynchronous Primitives

단일 비동기 작업을 수행 하 고 결과를 반환 하는 메서드를 비동기 기본 형식이라고 하며,이 메서드는에서 let!사용할 수 있도록 특별히 설계 되었습니다.A method that performs a single asynchronous task and returns the result is called an asynchronous primitive, and these are designed specifically for use with let!. F# 핵심 라이브러리에는 몇 가지 비동기 기본 형식이 정의 되어 있습니다.Several asynchronous primitives are defined in the F# core library. 웹 응용 프로그램에 대 한 이러한 두 메서드는 Microsoft.FSharp.Control.WebExtensions WebRequest.AsyncGetResponseWebClient.AsyncDownloadString모듈에서 정의 됩니다.Two such methods for Web applications are defined in the module Microsoft.FSharp.Control.WebExtensions: WebRequest.AsyncGetResponse and WebClient.AsyncDownloadString. 두 기본 형식은 URL을 지정 하 여 웹 페이지에서 데이터를 다운로드 합니다.Both primitives download data from a Web page, given a URL. AsyncGetResponse개체를 생성 하 고 AsyncDownloadString 웹 페이지에 대 한 HTML을 나타내는 문자열을 생성 합니다. System.Net.WebResponseAsyncGetResponse produces a System.Net.WebResponse object, and AsyncDownloadString produces a string that represents the HTML for a Web page.

비동기 i/o 작업에 대 한 여러 가지 기본 형식이 Microsoft.FSharp.Control.CommonExtensions 모듈에 포함 됩니다.Several primitives for asynchronous I/O operations are included in the Microsoft.FSharp.Control.CommonExtensions module. System.IO.Stream 클래스의 이러한 확장 메서드는 Stream.AsyncReadStream.AsyncWrite입니다.These extension methods of the System.IO.Stream class are Stream.AsyncRead and Stream.AsyncWrite.

전체 본문이 비동기 블록으로 묶여 있는 함수를 정의 하 여 고유한 비동기 기본 형식을 작성할 수도 있습니다.You can also write your own asynchronous primitives by defining a function whose complete body is enclosed in an async block.

F# 비동기 프로그래밍 모델을 사용 하 여 다른 비동기 모델에 대해 디자인 된 .NET Framework에서 비동기 메서드를 사용 하려면 F# Async 개체를 반환 하는 함수를 만듭니다.To use asynchronous methods in the .NET Framework that are designed for other asynchronous models with the F# asynchronous programming model, you create a function that returns an F# Async object. F# 라이브러리에는이 작업을 쉽게 수행할 수 있도록 하는 함수가 있습니다.The F# library has functions that make this easy to do.

비동기 워크플로를 사용 하는 한 가지 예는 여기에 포함 되어 있습니다. 비동기 클래스의 메서드에 대 한 설명서에는 다른 여러 가지가 있습니다.One example of using asynchronous workflows is included here; there are many others in the documentation for the methods of the Async class.

이 예제에서는 비동기 워크플로를 사용 하 여 계산을 병렬로 수행 하는 방법을 보여 줍니다.This example shows how to use asynchronous workflows to perform computations in parallel.

다음 코드 예제에서 함수 fetchAsync 는 웹 요청에서 반환 된 HTML 텍스트를 가져옵니다.In the following code example, a function fetchAsync gets the HTML text returned from a Web request. 함수 fetchAsync 에는 비동기 코드 블록이 포함 되어 있습니다.The fetchAsync function contains an asynchronous block of code. 비동기 기본 형식 (이 경우 AsyncDownloadString)의 결과에 대 한 바인딩이 수행 되 면When a binding is made to the result of an asynchronous primitive, in this case AsyncDownloadString, let! 는 let 대신 사용 됩니다.is used instead of let.

함수 Async.RunSynchronously 를 사용 하 여 비동기 작업을 실행 하 고 그 결과를 기다립니다.You use the function Async.RunSynchronously to execute an asynchronous operation and wait for its result. 예를 들어 함수와 함께 함수 Async.Parallel Async.RunSynchronously 를 사용 하 여 여러 비동기 작업을 병렬로 실행할 수 있습니다.As an example, you can execute multiple asynchronous operations in parallel by using the Async.Parallel function together with the Async.RunSynchronously function. 함수 Async.Parallel Async 는 개체 목록을 가져오고, 각 Async 작업 개체에 대해 병렬로 실행 Async 되도록 코드를 설정 하 고, 병렬 계산을 나타내는 개체를 반환 합니다.The Async.Parallel function takes a list of the Async objects, sets up the code for each Async task object to run in parallel, and returns an Async object that represents the parallel computation. 단일 작업의 경우와 마찬가지로를 호출 Async.RunSynchronously 하 여 실행을 시작 합니다.Just as for a single operation, you call Async.RunSynchronously to start the execution.

함수 runAll 는 세 개의 비동기 워크플로를 병렬로 시작 하 고 모든 작업이 완료 될 때까지 대기 합니다.The runAll function launches three asynchronous workflows in parallel and waits until they have all completed.

open System.Net
open Microsoft.FSharp.Control.WebExtensions

let urlList = [ "Microsoft.com", "http://www.microsoft.com/"
                "MSDN", "http://msdn.microsoft.com/"
                "Bing", "http://www.bing.com"
              ]

let fetchAsync(name, url:string) =
    async {
        try
            let uri = new System.Uri(url)
            let webClient = new WebClient()
            let! html = webClient.AsyncDownloadString(uri)
            printfn "Read %d characters for %s" html.Length name
        with
            | ex -> printfn "%s" (ex.Message);
    }

let runAll() =
    urlList
    |> Seq.map fetchAsync
    |> Async.Parallel
    |> Async.RunSynchronously
    |> ignore

runAll()

참고자료See also