Partilhar via


Fluxos de trabalho assíncronos (F#)

Este tópico descreve o suporte no F# para executar cálculos assincronamente, isto é, sem bloquear a execução de outro trabalho. Por exemplo, computações assíncronas podem ser usadas para escrever aplicativos que possuem interfaces de usuário permaneçam responsivos a usuários, como o aplicativo execute outro trabalho.

async { expression }

Comentários

Na sintaxe anterior, a computação é representado por expression está configurado para ser executados de forma assíncrona, ou seja, sem bloquear o thread de computação atual quando operações de suspensão assíncrona, e/S e outras operações assíncronas são realizadas. Computações assíncronas geralmente são iniciadas em um thread de segundo plano, enquanto a execução continua no segmento atual. O tipo da expressão é Async<'a>, onde 'a é o tipo retornado pela expressão quando o return palavra-chave é usada. O código em uma expressão como essa é conhecido como um assíncrono bloco, ou async bloco.

Há várias maneiras de programação assíncrona e o Async classe fornece métodos que oferecem suporte a vários cenários. A abordagem geral é criar Async objetos que representam a computação ou computações que você deseja executar de forma assíncrona e inicie essas computações usando uma das funções de disparo. As várias funções de disparo fornecem diferentes maneiras de executar as computações assíncronas e que você pode usar depende se você deseja usar o segmento atual, um segmento de plano de fundo ou um.Objeto de tarefa do NET Framework, e se há funções de continuação devem ser executado quando termina de computação. Por exemplo, para iniciar uma computação assíncrona no thread atual, você pode usar Async.StartImmediate. Quando você inicia uma computação assíncrona do thread da interface do usuário, você não bloqueie o loop principal do evento que processa as ações do usuário como, por exemplo, pressionamentos de tecla e a atividade do mouse, para que seu aplicativo permaneça responsivo.

Vinculação assíncrona usando let!

Em um fluxo de trabalho assíncrono, algumas operações e as expressões são síncronas e alguns são mais cálculos que são projetados para retornar um resultado de forma assíncrona. Quando você chama um método de forma assíncrona, em vez de um comum let de vinculação, use let!. O efeito de let! é permitir a execução continue em outros cálculos ou segmentos, como a computação está sendo executada. Após o lado direito da let! ligação retorna o resto do fluxo de trabalho assíncrono reinicia a execução.

O código a seguir mostra a diferença entre let e let!. A linha de código que usa let apenas cria uma computação assíncrona como um objeto que pode ser executado posteriormente, usando, por exemplo, Async.StartImmediate ou Async.RunSynchronously. A linha de código que usa let! inicia a computação e, em seguida, o thread está suspenso até que o resultado esteja disponível, no qual ponto a execução continua.

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

Além dos let!, você pode usar use! para executar as vinculações assíncronas. A diferença entre let! e use! é o mesmo que a diferença entre let e use. Para use!, o objeto é descartado no fechamento do escopo atual. Observe que na versão atual do idioma F#, use! não aceita um valor a ser inicializadas como null, embora use faz.

Primitivos assíncronos

Um método que executa uma única tarefa assíncrona e retorna o resultado é chamado um primitivo assíncrono, e elas foram desenvolvidas especificamente para uso com o let!. Vários primitivos assíncronos são definidos na biblioteca do núcleo F#. Dois desses métodos para aplicativos da Web são definidos no módulo Microsoft.FSharp.Control.WebExtensions: WebRequest.AsyncGetResponse e WebClient.AsyncDownloadString. Ambos os primitivos de baixar dados a partir de uma página da Web, fornecida uma URL. AsyncGetResponseproduz uma WebResponse o objeto, e AsyncDownloadString produz uma seqüência de caracteres que representa o HTML para uma página da Web.

Primitivos de vários para operações de e/S assíncronas são incluídos na Microsoft.FSharp.Control.CommonExtensions module. Esses métodos de extensão da Stream classe são Stream.AsyncRead e Stream.AsyncWrite.

Os primitivos assíncronos adicionais estão disponíveis a PowerPack F#. Você também pode escrever seus próprios primitivos assíncronos, definindo uma função cujo corpo total está contido em um bloco de async.

Para usar os métodos assíncronos na.NET Framework são projetados para outros modelos assíncronos com o F# modelo de programação assíncrona, que você criar uma função que retorna um F# Async objeto. A biblioteca do F# possui funções que tornam isso fácil de fazer.

Um exemplo de uso de fluxos de trabalho assíncronos é incluído aqui; Existem muitos outros na documentação para os métodos da a classe de Async.

Exemplo

Este exemplo mostra como usar os fluxos de trabalho assíncronos para executar cálculos em paralelo.

No seguinte exemplo de código, uma função fetchAsync obtém o texto HTML retornado de uma solicitação da Web. O fetchAsync função contém um bloco assíncrono de código. Quando uma ligação é feita para o resultado de um primitivo assíncrono, neste caso AsyncDownloadString, let! é usado em vez de let.

Você usar a função Async.RunSynchronously para executar uma operação assíncrona e aguarde seu resultado. Por exemplo, você poderá executar várias operações assíncronas em paralelo usando o Async funcionam em conjunto com o Async.RunSynchronously função. O Async.Parallel função leva a uma lista da Async objetos, configura o código para cada Async o objeto de tarefa para executar em paralelo e retorna um Async objeto que representa a computação paralela. Apenas para uma única operação, você chamar Async.RunSynchronously para iniciar a execução.

O runAll função inicia três fluxos de trabalho assíncronos em paralelo e aguarda até que eles tenham concluído.

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

let urlList = [ "Microsoft.com", "https://www.microsoft.com/"
                "MSDN", "https://msdn.microsoft.com/"
                "Bing", "https://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()

Consulte também

Referência

Classe Control.Async (F #)

Outros recursos

Referência de linguagem do F#

Expressões de computação (F#)

Histórico de alterações

Date

History

Motivo

Outubro de 2010

Esclarecida que nem todas as operações assíncronas ocorrerem em um segmento de plano de fundo.

Aprimoramento de informações.