Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
FSharp.Core 11 agrega funciones para la interoperabilidad de tareas, las transformaciones de resultados y la simultaneidad limitada. Úselas con flujos de trabajo asincrónicos y expresiones de tareas existentes; no requieren el prototipo en tiempo de ejecución asincrónico.
Await .NET operaciones desde asincrónico
Para iniciar una operación de .NET con el token de cancelación del flujo de trabajo asincrónico, pase un generador a Async.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
}
La lectura del archivo recibe el token de cancelación del flujo de trabajo. Un archivo que falta devuelve None; una lectura correcta devuelve Some contents. El flujo de trabajo espera la finalización, incluida la cancelación y la limpieza.
Úselo Async.Await cuando ya tenga un valor similar a una tarea. Ambas API propagan directamente la única excepción subyacente de una tarea con errores. Un agregado con varias excepciones internas sigue siendo un agregado.
Async.AwaitTask mantiene su comportamiento de ajuste de excepciones existente.
| API | Formas de argumento/resultado admitidas |
|---|---|
Async.Await |
Task<'T> -> Async<'T>; Task -> Async<unit> |
Async.Await |
ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit> |
Async.Await |
Sobrecarga similar a tareas insertadas mediante el GetAwaiter protocolo . |
Async.StartTaskImmediate |
(CancellationToken -> Task<'T>) -> Async<'T>; no genérico Task devuelve Async<unit>. |
Async.StartTaskImmediate |
Las sobrecargas de fábrica de tareas , ValueTask<'T>y correspondientesValueTask. |
Task.startAsyncImmediate |
CancellationToken -> Async<'T> -> Task<'T> |
Async.RunSynchronouslyImmediate |
Async<'T> * ?cancellationToken: CancellationToken -> 'T |
Async.RunSynchronouslyImmediate se inicia en el subproceso que realiza la llamada, a diferencia Async.RunSynchronously de en un subproceso en primer plano, y bloquea la finalización. No tiene ningún parámetro de tiempo de espera. Prefiere la composición asincrónica en la interfaz de usuario y los subprocesos de solicitud.
Exponer un flujo de trabajo asincrónico como una tarea
Para ofrecer el flujo de trabajo de lectura de archivos anterior a los autores de llamadas basados en tareas, acepte un token de cancelación y páselo a través de Task.startAsyncImmediate:
let tryReadFileTask (path: string) (ct: CancellationToken) =
tryReadFile path |> Task.startAsyncImmediate ct
El puente devuelve Task<string option> y propaga la cancelación. Se inicia en el subproceso que llama hasta la primera suspensión; Las continuaciones posteriores no necesitan usar ese subproceso.
Simultaneidad enlazada
Un Async<'T> valor describe el trabajo diferido. Normalmente, una tarea representa una operación que ya se ha iniciado. Para limitar el uso de recursos, describa el trabajo de tareas como factorías en lugar de tareas ya en ejecución:
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 comienza como máximo el límite positivo de cálculos simultáneamente y devuelve resultados en orden de entrada. El orden de inicio y el orden de finalización no se especifican. Para la simultaneidad mayor que una, cada fábrica recibe un token vinculado que también indica un error relacionado; para la ejecución secuencial recibe el token proporcionado directamente.
Cuando se produce un error de cálculo, se solicita la cancelación para sus elementos del mismo nivel. Las operaciones deben observar sus tokens para cooperar. Si se produce un error en varios cálculos, se propaga una excepción; no dependen de qué fracaso gana.
| Función | Forma de firma |
|---|---|
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> |
Las Async funciones fluyen el token de cancelación ambiental del flujo de trabajo. Existente Async.Parallel (incluida su opción de límite de simultaneidad) y Async.Sequential permanece disponible. Las Do variantes exponen un unit resultado cuando solo necesita finalización. Un límite de simultaneidad no es un limitador de velocidad: las operaciones rápidas pueden producir muchas solicitudes por segundo.
Transformación de resultados y recuperación de errores
Los Microsoft.FSharp.Control.Asyncmódulos , Tasky ValueTask exponen estas funciones calificadas.
M<'T> en la columna shape representa el tipo de cálculo correspondiente, no una abreviatura de tipo F#.
| Funciones calificadas | Forma |
|---|---|
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>; se requiere un argumento de tipo de entrada explícito. |
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 ejemplo, asigne el contenido de un archivo a una longitud y, a continuación, represente un error de lectura como :Result
open System.IO
open System.Threading
let fileLength (path: string) (ct: CancellationToken) =
File.ReadAllTextAsync(path, ct)
|> Task.map String.length
|> Task.catch
Un archivo que contiene Report 1 proporciona Ok 8. Un archivo que falta proporciona un Error objeto que contiene .FileNotFoundException Para descartar un valor correcto en lugar de transformarlo, especifique el tipo de entrada al llamar a ignore:
let completion: System.Threading.Tasks.Task<unit> =
Task.result 42 |> Task.ignore<int>
catchWith proporciona un valor de reemplazo para un error de no cancelación; no ejecuta otro cálculo asincrónico.
catch devuelve Ok o Error. La cancelación no se convierte en un valor de error ni se pasa al controlador de recuperación.
Task.empty es , Task<unit>no es el no genérico Task.CompletedTask.
A diferencia de en minúsculas Async.catch, existing Async.Catch devuelve Choice. La recuperación controla los errores del cálculo proporcionado, no las excepciones sincrónicas que se producen antes de la llamada. Async permanece diferido; las tareas permanecen diligentes.
Disponibilidad de ValueTask y biblioteca
Las API de ValueTask requieren la netstandard2.1 compilación o net10.0 de FSharp.Core 11. Consulte Selección de destino principal.
Observe el contrato valueTask de consumo único: consume cada valor una vez, no a través de esperas o canalizaciones independientes. Para las esperas repetidas, llame Task.ofValueTask una vez y reutilice solo la tarea resultante.