Asynchronní funkce a funkce úloh

FSharp.Core 11 přidává funkce pro interoperabilitu úkolů, transformace výsledků a ohraničenou souběžnost. Používejte je s existujícími asynchronními pracovními postupy a výrazy úkolů; nevyžadují prototyp modulu runtime async.

Operace Await .NET z asynchronních operací

Pokud chcete zahájit operaci .NET pomocí tokenu zrušení asynchronního pracovního postupu, předejte objektu pro Async.StartTaskImmediatevytváření:

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
    }

Čtení souboru obdrží token zrušení pracovního postupu. Chybějící soubor vrátí None; úspěšné čtení vrátí Some contents. Pracovní postup čeká na dokončení, včetně zrušení a vyčištění.

Použijte Async.Await , pokud už máte hodnotu podobné úkolu. Obě rozhraní API šíří jedinou základní výjimku chybné úlohy přímo. Agregace s více vnitřními výjimkami zůstává agregací. Async.AwaitTask zachová stávající chování při obtékání výjimek.

API Podporované obrazce argumentů a výsledků
Async.Await Task<'T> -> Async<'T>; Task -> Async<unit>
Async.Await ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit>
Async.Await Vložené přetížení podobné úkolu pomocí GetAwaiter protokolu.
Async.StartTaskImmediate (CancellationToken -> Task<'T>) -> Async<'T>; negenerické Task návraty Async<unit>.
Async.StartTaskImmediate Odpovídající ValueTaskpřetížení objektu pro ValueTask<'T>vytváření a podobné úlohám.
Task.startAsyncImmediate CancellationToken -> Async<'T> -> Task<'T>
Async.RunSynchronouslyImmediate Async<'T> * ?cancellationToken: CancellationToken -> 'T

Async.RunSynchronouslyImmediate začíná na volajícím vlákně, na rozdíl od Async.RunSynchronously vlákna popředí a bloků pro dokončení. Nemá žádný parametr časového limitu. Upřednostněte asynchronní složení ve vláknech uživatelského rozhraní a požadavků.

Zveřejnění asynchronního pracovního postupu jako úkolu

Chcete-li nabídnout výše uvedený pracovní postup čtení souborů volajícím na základě úloh, přijměte token zrušení a předejte Task.startAsyncImmediateho:

let tryReadFileTask (path: string) (ct: CancellationToken) =
    tryReadFile path |> Task.startAsyncImmediate ct

Most se vrátí Task<string option> a rozšíří zrušení. Začíná na volajícím vlákně až do prvního pozastavení; další pokračování nemusí toto vlákno používat.

Svázaná souběžnost

Hodnota Async<'T> popisuje odloženou práci. Úkol obvykle představuje operaci, která už byla spuštěna. Pokud chcete omezit použití zdrojů, popište úlohu jako továrny, nikoli jako již spuštěné úkoly:

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 začíná maximálně kladným limitem výpočtů současně a vrací výsledky ve vstupním pořadí. Pořadí zahájení a dokončení není jinak zadáno. V případě souběžnosti větší než jedna obdrží každá továrna propojený token, který také signalizuje selhání stejné kategorie; pro postupné spuštění obdrží zadaný token přímo.

Když dojde k jedné chybě výpočtu, požádá se o zrušení na stejné úrovni. Operace musí sledovat své tokeny, aby spolupracovaly. Pokud selže několik výpočtů, rozšíří se jedna výjimka; nezávisí na tom, která chyba vyhraje.

Function Obrazec podpisu
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>

Funkce Async protékají token okolního zrušení pracovního postupu. Stávající Async.Parallel (včetně možnosti souběžnosti) a Async.Sequential zůstávají dostupné. Varianty Do zpřístupňují unit výsledek pouze v případě, že potřebujete dokončit. Limit souběžnosti není limit rychlosti: rychlé operace můžou stále vytvářet mnoho požadavků za sekundu.

Transformace výsledků a zotavení z chyb

Moduly Microsoft.FSharp.Control.Asynca ValueTask , Taskzveřejňují tyto kvalifikované funkce. M<'T> ve sloupci obrazce představuje odpovídající typ výpočtu, nikoli zkratku typu jazyka F#.

Kvalifikované funkce 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>; explicitní argument vstupního typu je povinný.
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>

Například namapujte obsah souboru na délku a pak představuje chybu čtení jako Result:

open System.IO
open System.Threading

let fileLength (path: string) (ct: CancellationToken) =
    File.ReadAllTextAsync(path, ct)
    |> Task.map String.length
    |> Task.catch

Soubor obsahující Report 1 soubor dává Ok 8. Chybějící soubor obsahuje ErrorFileNotFoundException. Pokud chcete zahodit úspěšnou hodnotu, nikoli ji transformovat, zadejte při volání ignorevstupní typ:

let completion: System.Threading.Tasks.Task<unit> =
    Task.result 42 |> Task.ignore<int>

catchWith poskytuje náhradní hodnotu selhání, která není zrušena; nespusí další asynchronní výpočty. catch vrátí Ok nebo Error. Zrušení není převedeno na chybovou hodnotu nebo předáno obslužné rutině obnovení. Task.empty je , Task<unit>ne obecné Task.CompletedTask.

Na rozdíl od malých písmen Async.catch, existující Async.Catch vrací Choice. Obnovení zpracovává selhání zadaného výpočtu, ne synchronní výjimky vyvolané před voláním. Asynchronní synchronizace zůstává odložena; úkoly zůstávají dychtivé.

Dostupnost valueTask a knihovny

Rozhraní API ValueTask vyžadují netstandard2.1 nebo net10.0 sestavte FSharp.Core 11. Viz Výběr cíle jádra.

Prohlédněte si kontrakt ValueTask s jednou spotřebou: jednotlivé hodnoty spotřebovávejte jednou, ne prostřednictvím samostatných čekajících nebo kanálů. U opakovaných čekání zavolejte Task.ofValueTask jednou a znovu použijte pouze výsledný úkol.

Viz také