Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
FSharp.Core 11 fügt Funktionen für die Vorgangsinterteroperabilität, Ergebnistransformationen und begrenzungsgebundene Parallelität hinzu. Verwenden Sie sie mit vorhandenen asynchronen Workflows und Aufgabenausdrücken; sie benötigen nicht den asynchronen Laufzeitprototyp.
Await .NET operations from async
Um einen .NET Vorgang mit dem Abbruchtoken des asynchronen Workflows zu starten, übergeben Sie eine Factory anAsync.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
}
Die Dateilesevorgang empfängt das Abbruchtoken des Workflows. Eine fehlende Datei gibt zurück None; ein erfolgreicher Lesevorgang wird zurückgegeben Some contents. Der Workflow wartet auf den Abschluss, einschließlich Abbruch und Bereinigung.
Verwenden Sie diese Methode Async.Await , wenn Sie bereits einen vorgangsähnlichen Wert haben. Beide APIs verteilen die einzelne zugrunde liegende Ausnahme eines fehlerhaften Vorgangs direkt. Ein Aggregat mit mehreren inneren Ausnahmen bleibt ein Aggregat.
Async.AwaitTask behält das vorhandene Ausnahmeumbruchverhalten bei.
| API | Unterstützte Argument-/Ergebnis-Shapes |
|---|---|
Async.Await |
Task<'T> -> Async<'T>; Task -> Async<unit> |
Async.Await |
ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit> |
Async.Await |
Inlineaufgabenähnliche Überladung mithilfe des GetAwaiter Protokolls. |
Async.StartTaskImmediate |
(CancellationToken -> Task<'T>) -> Async<'T>; nicht generische Task Rückgaben Async<unit>. |
Async.StartTaskImmediate |
Entsprechende ValueTask, ValueTask<'T>und aufgabenähnliche Factoryüberladungen. |
Task.startAsyncImmediate |
CancellationToken -> Async<'T> -> Task<'T> |
Async.RunSynchronouslyImmediate |
Async<'T> * ?cancellationToken: CancellationToken -> 'T |
Async.RunSynchronouslyImmediate startet im aufrufenden Thread, im Gegensatz zu Async.RunSynchronously einem Vordergrundthread und Blöcken für den Abschluss. Es hat keinen Timeoutparameter. Bevorzugen Sie die asynchrone Komposition auf der Benutzeroberfläche und Anforderungsthreads.
Verfügbarmachen eines asynchronen Workflows als Aufgabe
Um den obigen Dateileseworkflow für aufgabenbasierte Aufrufer anzubieten, akzeptieren Sie ein Abbruchtoken und übergeben Sie ihn durch Task.startAsyncImmediate:
let tryReadFileTask (path: string) (ct: CancellationToken) =
tryReadFile path |> Task.startAsyncImmediate ct
Die Brücke gibt den Abbruch zurück Task<string option> und verteilt sie. Er beginnt auf dem aufrufenden Thread bis zum ersten Anhalten; spätere Fortsetzungen müssen diesen Thread nicht verwenden.
Gebundene Parallelität
Ein Async<'T> Wert beschreibt verzögerte Arbeit. Eine Aufgabe stellt in der Regel einen Vorgang dar, der bereits gestartet wurde. Um die Ressourcennutzung einzuschränken, beschreiben Sie die Vorgangsarbeit als Fabriken und nicht als bereits ausgeführte Vorgänge:
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 beginnt höchstens das positive Limit der Berechnungen gleichzeitig und gibt Ergebnisse in der Eingabereihenfolge zurück. Die Anfangsreihenfolge und der Abschlussauftrag sind andernfalls nicht angegeben. Für Parallelität, die größer als eine ist, empfängt jede Factory ein verknüpftes Token, das auch gleichgeordnete Fehler signalisiert; für die sequenzielle Ausführung empfängt es das bereitgestellte Token direkt.
Wenn eine Berechnungsfehler aufgetreten ist, wird der Abbruch für seine gleichgeordneten Daten angefordert. Vorgänge müssen ihre Token beachten, um zusammenzuarbeiten. Wenn mehrere Berechnungen fehlschlagen, wird eine Ausnahme weitergegeben; sie hängen nicht davon ab, welche Fehler siegen.
| Funktion | Signatur-Shape |
|---|---|
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> |
Die Async Funktionen fließen im Umgebungsabbruchtoken des Workflows. Vorhanden Async.Parallel (einschließlich der Parallelitätsbeschränkungsoption) und Async.Sequential bleiben verfügbar. Die Do Varianten machen ein unit Ergebnis verfügbar, wenn Sie nur den Abschluss benötigen. Ein Parallelitätslimit ist kein Zinsgrenzwert: Schnelle Vorgänge können weiterhin viele Anforderungen pro Sekunde erzeugen.
Transformieren von Ergebnissen und Wiederherstellen von Fehlern
Die Microsoft.FSharp.Control.AsyncModule und ValueTask Die Module Taskmachen diese qualifizierten Funktionen verfügbar.
M<'T> in der Formspalte steht für den entsprechenden Berechnungstyp, nicht für eine F#-Typabkürzung.
| Qualifizierte Funktionen | Gestalt |
|---|---|
Async.result, Task.resultValueTask.result |
'T -> M<'T> |
Async.map, Task.mapValueTask.map |
('T -> 'U) -> M<'T> -> M<'U> |
Async.bind, Task.bindValueTask.bind |
('T -> M<'U>) -> M<'T> -> M<'U> |
Async.ignore<'T>, Task.ignore<'T>ValueTask.ignore<'T> |
M<'T> -> M<unit>; Explizites Eingabetypargument erforderlich. |
Async.catchWith, Task.catchWithValueTask.catchWith |
(exn -> 'T) -> M<'T> -> M<'T> |
Async.catch, Task.catchValueTask.catch |
M<'T> -> M<Result<'T, exn>> |
Async.empty, Task.emptyValueTask.empty |
M<unit> |
Task.ofValueTask |
ValueTask<'T> -> Task<'T> |
ValueTask.ofTask |
Task<'T> -> ValueTask<'T> |
Ordnen Sie z. B. den Inhalt einer Datei einer Länge zu, und stellen Sie dann einen Lesefehler als :Result
open System.IO
open System.Threading
let fileLength (path: string) (ct: CancellationToken) =
File.ReadAllTextAsync(path, ct)
|> Task.map String.length
|> Task.catch
Eine Datei, die die Datei enthält Report 1 , gibt Ok 8. Eine fehlende Datei enthält eine Error .FileNotFoundException Wenn Sie einen erfolgreichen Wert verwerfen möchten, anstatt ihn zu transformieren, geben Sie den Eingabetyp beim Aufrufen ignorean:
let completion: System.Threading.Tasks.Task<unit> =
Task.result 42 |> Task.ignore<int>
catchWith liefert einen Ersatzwert für einen Ausfall ohne Abbruch; es wird keine andere asynchrone Berechnung ausgeführt.
catch gibt zurück Ok oder Error. Der Abbruch wird nicht in einen Fehlerwert konvertiert oder an den Wiederherstellungshandler übergeben.
Task.empty ist ein Task<unit>, nicht das nicht generische Task.CompletedTask.
Im Gegensatz zu Kleinbuchstaben Async.catchgibt vorhandene Async.Catch Rückgaben Choicezurück. Die Wiederherstellung behandelt Fehler der bereitgestellten Berechnung, nicht synchrone Ausnahmen, die vor dem Aufruf ausgelöst werden. Async bleibt zurückgestellt; Aufgaben bleiben begierig.
ValueTask- und Bibliotheksverfügbarkeit
ValueTask-APIs erfordern den netstandard2.1 Oder net10.0 Build von FSharp.Core 11. Siehe Kernzielauswahl.
Beobachten Sie den WertTask-Einzelverbrauchsvertrag: Verbrauchen Sie jeden Wert einmal, nicht durch separate Awaits oder Pipelines. Rufen Sie bei wiederholten Awaits einmal auf Task.ofValueTask , und verwenden Sie nur die resultierende Aufgabe.