Flujos de trabajo asincrónicosAsynchronous Workflows

Nota

El vínculo de la referencia de API le llevará a MSDN.The API reference link will take you to MSDN. La referencia de API de docs.microsoft.com no está completa.The docs.microsoft.com API reference is not complete.

En este tema se describe F# la compatibilidad de para realizar cálculos de forma asincrónica, es decir, sin bloquear la ejecución de otro trabajo.This topic describes support in F# for performing computations asynchronously, that is, without blocking execution of other work. Por ejemplo, los cálculos asincrónicos se pueden usar para escribir aplicaciones que tengan interfaces de usuario que sigan respondiendo a los usuarios a medida que la aplicación realice otro trabajo.For example, asynchronous computations can be used to write applications that have UIs that remain responsive to users as the application performs other work.

SintaxisSyntax

async { expression }

ComentariosRemarks

En la sintaxis anterior, el cálculo representado por expression está configurado para ejecutarse de forma asincrónica, es decir, sin bloquear el subproceso de cálculo actual cuando se realizan operaciones asincrónicas de suspensión, e/s y otras operaciones asincrónicas.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. A menudo, los cálculos asincrónicos se inician en un subproceso en segundo plano mientras la ejecución continúa en el subproceso actual.Asynchronous computations are often started on a background thread while execution continues on the current thread. El tipo de la expresión es Async<'T>, donde 'T es el tipo devuelto por la expresión cuando return se usa la palabra clave.The type of the expression is Async<'T>, where 'T is the type returned by the expression when the return keyword is used. El código en una expresión de este tipo se conoce como un bloque asincrónicoo un bloque asincrónico.The code in such an expression is referred to as an asynchronous block, or async block.

Hay varias maneras de programar de forma asincrónica y la Async clase proporciona métodos que admiten varios escenarios.There are a variety of ways of programming asynchronously, and the Async class provides methods that support several scenarios. El enfoque general es crear Async objetos que representan el cálculo o los cálculos que desea ejecutar de forma asincrónica y, a continuación, iniciar estos cálculos mediante una de las funciones de desencadenamiento.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. Las distintas funciones de desencadenador proporcionan diferentes maneras de ejecutar cálculos asincrónicos y la que se usa depende de si se desea usar el subproceso actual, un subproceso en segundo plano o un objeto de tarea .NET Framework, y si hay continuación. funciones que se deben ejecutar cuando finaliza el cálculo.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. Por ejemplo, para iniciar un cálculo asincrónico en el subproceso actual, puede usar Async.StartImmediate.For example, to start an asynchronous computation on the current thread, you can use Async.StartImmediate. Cuando se inicia un cálculo asincrónico desde el subproceso de la interfaz de usuario, no se bloquea el bucle de eventos principal que procesa las acciones del usuario, como pulsaciones de teclas y actividad del mouse, para que la aplicación siga respondiendo.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.

Enlace asincrónico mediante Let!Asynchronous Binding by Using let!

En un flujo de trabajo asincrónico, algunas expresiones y operaciones son sincrónicas y otras son cálculos más largos que están diseñados para devolver un resultado de forma asincrónica.In an asynchronous workflow, some expressions and operations are synchronous, and some are longer computations that are designed to return a result asynchronously. Cuando se llama a un método de forma asincrónica, en lugar let de un enlace normal let!, se usa.When you call a method asynchronously, instead of an ordinary let binding, you use let!. El efecto de let! es permitir que la ejecución continúe en otros cálculos o subprocesos mientras se realiza el cálculo.The effect of let! is to enable execution to continue on other computations or threads as the computation is being performed. Una vez que el lado derecho let! del enlace vuelve, el resto del flujo de trabajo asincrónico reanuda la ejecución.After the right side of the let! binding returns, the rest of the asynchronous workflow resumes execution.

En el código siguiente se muestra la let diferencia let!entre y.The following code shows the difference between let and let!. La línea de código que usa let simplemente crea un cálculo asincrónico como un objeto que se puede ejecutar más adelante mediante, por ejemplo, Async.StartImmediate o 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. La línea de código que usa let! inicia el cálculo y, a continuación, el subproceso se suspende hasta que el resultado esté disponible, momento en el que continúa la ejecución.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)

Además let!de, puede usar use! para realizar enlaces asincrónicos.In addition to let!, you can use use! to perform asynchronous bindings. La diferencia entre let! y use! es la misma que la diferencia entre let y use.The difference between let! and use! is the same as the difference between let and use. En use!el caso de, el objeto se desecha al cerrar el ámbito actual.For use!, the object is disposed of at the close of the current scope. Tenga en cuenta que en la versión actual F# del lenguaje use! , no permite que un valor se inicialice en use null, aunque sí lo hace.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.

Primitivas asincrónicasAsynchronous Primitives

Un método que realiza una única tarea asincrónica y devuelve el resultado se denomina primitiva asincrónica, y se ha diseñado específicamente para su uso con 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!. Se definen varias primitivas asincrónicas en la F# biblioteca principal.Several asynchronous primitives are defined in the F# core library. En el módulo Microsoft.FSharp.Control.WebExtensionsse definen dos métodos de este tipo para las aplicaciones WebClient.AsyncDownloadStringWeb: WebRequest.AsyncGetResponse y.Two such methods for Web applications are defined in the module Microsoft.FSharp.Control.WebExtensions: WebRequest.AsyncGetResponse and WebClient.AsyncDownloadString. Ambos primitivos descargan datos de una página web, dada una dirección URL.Both primitives download data from a Web page, given a URL. AsyncGetResponsegenera un System.Net.WebResponse objeto y AsyncDownloadString genera una cadena que representa el código HTML de una página web.AsyncGetResponse produces a System.Net.WebResponse object, and AsyncDownloadString produces a string that represents the HTML for a Web page.

En el Microsoft.FSharp.Control.CommonExtensions módulo se incluyen varios primitivos para las operaciones de e/s asincrónicas.Several primitives for asynchronous I/O operations are included in the Microsoft.FSharp.Control.CommonExtensions module. Estos métodos de extensión de System.IO.Stream la clase Stream.AsyncRead son Stream.AsyncWritey.These extension methods of the System.IO.Stream class are Stream.AsyncRead and Stream.AsyncWrite.

También puede escribir sus propias primitivas asincrónicas definiendo una función cuyo cuerpo completo esté incluido en un bloque asincrónico.You can also write your own asynchronous primitives by defining a function whose complete body is enclosed in an async block.

Para usar métodos asincrónicos en el .NET Framework que están diseñados para otros modelos asincrónicos con el F# modelo de programación asincrónica, cree una función que devuelva un F# Async objeto.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. La F# biblioteca tiene funciones que facilitan esta tarea.The F# library has functions that make this easy to do.

Aquí se incluye un ejemplo del uso de flujos de trabajo asíncronos. Hay muchas otras en la documentación de los métodos de la clase asincrónica.One example of using asynchronous workflows is included here; there are many others in the documentation for the methods of the Async class.

En este ejemplo se muestra cómo usar flujos de trabajo asincrónicos para realizar cálculos en paralelo.This example shows how to use asynchronous workflows to perform computations in parallel.

En el ejemplo de código siguiente, una fetchAsync función obtiene el texto HTML devuelto de una solicitud Web.In the following code example, a function fetchAsync gets the HTML text returned from a Web request. La fetchAsync función contiene un bloque de código asincrónico.The fetchAsync function contains an asynchronous block of code. Cuando se realiza un enlace al resultado de una primitiva asincrónica, en este caso AsyncDownloadString, Let.When a binding is made to the result of an asynchronous primitive, in this case AsyncDownloadString, let! se usa en lugar de Let.is used instead of let.

Utilice la función Async.RunSynchronously para ejecutar una operación asincrónica y esperar su resultado.You use the function Async.RunSynchronously to execute an asynchronous operation and wait for its result. Por ejemplo, puede ejecutar varias operaciones asincrónicas en paralelo mediante la Async.Parallel función junto con la Async.RunSynchronously función.As an example, you can execute multiple asynchronous operations in parallel by using the Async.Parallel function together with the Async.RunSynchronously function. La Async.Parallel función toma una lista de los Async objetos, configura el código para que cada Async objeto de tarea se ejecute en paralelo y devuelve un Async objeto que representa el cálculo en paralelo.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. Al igual que en el caso de una sola Async.RunSynchronously operación, se llama a para iniciar la ejecución.Just as for a single operation, you call Async.RunSynchronously to start the execution.

La runAll función inicia tres flujos de trabajo asincrónicos en paralelo y espera hasta que se hayan completado.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()

Vea tambiénSee also