Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O FSharp.Core 11 adiciona funções para interoperabilidade de tarefas, transformações de resultados e concorrência limitada. Use-os com fluxos de trabalho assíncronos e expressões de tarefa já existentes; não requerem o protótipo assíncrono em tempo de execução.
Aguardar operações .NET a partir de assíncronas
Para iniciar uma operação .NET com o token de cancelamento do fluxo de trabalho assíncrono, passe uma ficha de fábrica paraAsync.StartTaskImmediate:
open System.IO
let tryReadFile path =
async {
try
let! contents =
Async.StartTaskImmediate(fun ct -> File.ReadAllTextAsync(path, ct))
return Some contents
with :? FileNotFoundException ->
return None
}
O ficheiro lido recebe o token de cancelamento do fluxo de trabalho. Um ficheiro em falta retorna None; uma leitura bem-sucedida retorna Some contents. O fluxo de trabalho aguarda a conclusão, incluindo cancelamento e limpeza.
Use Async.Await quando já tiver um valor semelhante a uma tarefa. Ambas as APIs propagam diretamente a única exceção subjacente de uma tarefa com falha. Um agregado com múltiplas exceções internas permanece um agregado.
Async.AwaitTask mantém o seu comportamento existente de envolvimento de exceções.
| API | Formas de argumento/resultado apoiadas |
|---|---|
Async.Await |
Task<'T> -> Async<'T>; Task -> Async<unit> |
Async.Await |
ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit> |
Async.Await |
Sobrecarga semelhante à tarefa inline usando o GetAwaiter protocolo. |
Async.StartTaskImmediate |
(CancellationToken -> Task<'T>) -> Async<'T>; retornos Async<unit>não genéricosTask. |
Async.StartTaskImmediate |
Correspondentes ValueTask, ValueTask<'T>, e sobrecargas de fábrica semelhantes a tarefas. |
Task.startAsyncImmediate |
CancellationToken -> Async<'T> -> Task<'T> |
Async.RunSynchronouslyImmediate |
Async<'T> * ?cancellationToken: CancellationToken -> 'T |
Async.RunSynchronouslyImmediate começa no thread que chama, ao contrário Async.RunSynchronously do thread em primeiro plano, e bloqueia para conclusão. Não tem parâmetro de timeout. Prefiro composição assíncrona em UI e threads de pedidos.
Expor um fluxo de trabalho assíncrono como uma tarefa
Para oferecer o fluxo de trabalho de leitura de ficheiros acima a chamadores baseados em tarefas, aceite um token de cancelamento e transmita-o Task.startAsyncImmediate:
let tryReadFileTask (path: string) (ct: CancellationToken) =
tryReadFile path |> Task.startAsyncImmediate ct
A ponte retorna Task<string option> e propaga o cancelamento. Começa na thread de chamada até à primeira suspensão; as continuações posteriores não precisam de usar essa thread.
Concorrência ligada
Um valor descreve Async<'T> trabalho diferido. Uma tarefa normalmente representa uma operação que já foi iniciada. Para limitar o uso de recursos, descreva o trabalho de tarefas como fábricas em vez de tarefas já em funcionamento:
open System.IO
open System.Threading
let readFiles (paths: seq<string>) (ct: CancellationToken) =
paths
|> Seq.map (fun path ->
fun token -> File.ReadAllTextAsync(path, token))
|> Task.parallelLimit 4 ct
Task.parallelLimit começa, no máximo, o limite positivo dos cálculos em simultâneo e retorna os resultados na ordem de entrada. A ordem de início e a ordem de conclusão não são especificadas. Para concorrência maior do que um, cada fábrica recebe um token ligado que também sinaliza falha entre irmãos; para execução sequencial, recebe diretamente o token fornecido.
Quando um cálculo falha, solicita-se o cancelamento para os seus irmãos. As operações devem observar os seus tokens para cooperar. Se vários cálculos falharem, propaga-se uma exceção; não dependam de qual falha vence.
| Function | Forma característica |
|---|---|
Task.parallelLimit |
int -> CancellationToken -> seq<CancellationToken -> Task<'T>> -> Task<'T[]> |
Task.parallelDoLimit |
int -> CancellationToken -> seq<CancellationToken -> Task<unit>> -> Task<unit> |
Task.sequential |
CancellationToken -> seq<CancellationToken -> Task<'T>> -> Task<'T[]> |
Task.sequentialDo |
CancellationToken -> seq<CancellationToken -> Task<unit>> -> Task<unit> |
Async.parallelLimit |
int -> seq<Async<'T>> -> Async<'T[]> |
Async.parallelDoLimit |
int -> seq<Async<unit>> -> Async<unit> |
Async.sequentialDo |
seq<Async<unit>> -> Async<unit> |
As Async funções transmitem o token de cancelamento ambiente do fluxo de trabalho. Existentes Async.Parallel (incluindo a opção de limite de concorrência) e Async.Sequential continuam disponíveis. As Do variantes revelam um unit resultado quando só precisas de completar. Um limite de concorrência não é um limitador de taxa: operações rápidas ainda podem produzir muitos pedidos por segundo.
Resultados de transformação e recuperação de falhas
Os módulos Microsoft.FSharp.Control.Async, Task, e ValueTask expõem estas funções qualificadas.
M<'T> na coluna shape representa o tipo de computação correspondente, não uma abreviatura do tipo F#.
| Funções qualificadas | Shape |
|---|---|
Async.result, Task.result, ValueTask.result |
'T -> M<'T> |
Async.map, Task.map, ValueTask.map |
('T -> 'U) -> M<'T> -> M<'U> |
Async.bind, Task.bind, ValueTask.bind |
('T -> M<'U>) -> M<'T> -> M<'U> |
Async.ignore<'T>, Task.ignore<'T>, ValueTask.ignore<'T> |
M<'T> -> M<unit>; é necessário argumento explícito do tipo de entrada. |
Async.catchWith, Task.catchWith, ValueTask.catchWith |
(exn -> 'T) -> M<'T> -> M<'T> |
Async.catch, Task.catch, ValueTask.catch |
M<'T> -> M<Result<'T, exn>> |
Async.empty, Task.empty, ValueTask.empty |
M<unit> |
Task.ofValueTask |
ValueTask<'T> -> Task<'T> |
ValueTask.ofTask |
Task<'T> -> ValueTask<'T> |
Por exemplo, mapear o conteúdo de um ficheiro para um comprimento, depois representar uma falha de leitura como um Result:
open System.IO
open System.Threading
let fileLength (path: string) (ct: CancellationToken) =
File.ReadAllTextAsync(path, ct)
|> Task.map String.length
|> Task.catch
Um ficheiro contendo Report 1 fornece Ok 8. Um ficheiro em falta dá a um Error contendo um FileNotFoundException. Para descartar um valor bem-sucedido em vez de o transformar, especifique o tipo de entrada quando chamar ignore:
let completion: System.Threading.Tasks.Task<unit> =
Task.result 42 |> Task.ignore<int>
catchWith fornece um valor de substituição para uma falha não relacionada com cancelamento; não executa outro cálculo assíncrono.
catch retorna Ok ou Error. O cancelamento não é convertido num valor de erro nem passado para o handler de recuperação.
Task.empty é um Task<unit>, não o não-genérico Task.CompletedTask.
Ao contrário das minúsculas Async.catch, os retornos Choiceexistentes Async.Catch . A recuperação trata das falhas do cálculo fornecido, não das exceções síncronas lançadas antes da chamada. O assíncrono mantém-se adiado; as tarefas continuam ansiosas.
ValueTask e disponibilidade da biblioteca
As APIs do ValueTask requerem a netstandard2.1 build net10.0 ou do FSharp.Core 11.
Ver seleção de alvos principais.
Observe o contrato de consumo único ValueTask: consuma cada valor uma vez, não através de awaits ou pipelines separados. Para esperas repetidas, chame Task.ofValueTask uma vez e reuse apenas a tarefa resultante.