Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
FSharp.Core 11 добавляет функции для взаимодействия задач, преобразований результатов и ограниченного параллелизма. Используйте их с существующими асинхронными рабочими процессами и выражениями задач; Они не требуют прототипа среды выполнения асинхронного прототипа.
Операции ожидания .NET из асинхронной
Чтобы запустить операцию .NET с маркером отмены асинхронного рабочего процесса, передайте фабрику 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
}
Файл считывает маркер отмены рабочего процесса. Отсутствующий файл возвращается None; возвращается Some contentsуспешное чтение. Рабочий процесс ожидает завершения, включая отмену и очистку.
Используйте, Async.Await если у вас уже есть значение, похожее на задачу. Оба API распространяют единственное базовое исключение неисправной задачи напрямую. Агрегат с несколькими внутренними исключениями остается агрегированным.
Async.AwaitTask сохраняет существующее поведение упаковки исключений.
| API | Поддерживаемые фигуры аргументов и результатов |
|---|---|
Async.Await |
Task<'T> -> Async<'T>; Task -> Async<unit> |
Async.Await |
ValueTask<'T> -> Async<'T>; ValueTask -> Async<unit> |
Async.Await |
Встроенная перегрузка, похожая GetAwaiter на задачу с помощью протокола. |
Async.StartTaskImmediate |
(CancellationToken -> Task<'T>) -> Async<'T>; не универсальные возвращаемыеTask.Async<unit> |
Async.StartTaskImmediate |
ValueTask<'T>Соответствующие ValueTaskперегрузки фабрики и задачи. |
Task.startAsyncImmediate |
CancellationToken -> Async<'T> -> Task<'T> |
Async.RunSynchronouslyImmediate |
Async<'T> * ?cancellationToken: CancellationToken -> 'T |
Async.RunSynchronouslyImmediate запускается в вызывающем потоке, в отличие от Async.RunSynchronously потока переднего плана, и блоки для завершения. У него нет параметра времени ожидания. Предпочитайте асинхронную композицию в пользовательском интерфейсе и запрашивать потоки.
Предоставление асинхронного рабочего процесса в качестве задачи
Чтобы предложить приведенный выше рабочий процесс чтения файлов вызывающим абонентам на основе задач, примите маркер отмены и передайте его через Task.startAsyncImmediate:
let tryReadFileTask (path: string) (ct: CancellationToken) =
tryReadFile path |> Task.startAsyncImmediate ct
Мост возвращает Task<string option> и распространяет отмену. Он начинается с вызывающего потока до первой приостановки; Более поздние продолжения не должны использовать этот поток.
Привязанная параллелизм
Значение Async<'T> описывает отложенную работу. Задача обычно представляет операцию, которая уже запущена. Чтобы ограничить использование ресурсов, опишите работу задачи в качестве фабрик, а не уже выполняемых задач:
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 начинается по крайней мере положительное ограничение вычислений одновременно и возвращает результаты в порядке ввода. Порядок запуска и порядок завершения не определены. Для параллелизма больше одного, каждая фабрика получает связанный маркер, который также сигнализирует о сбое брата; для последовательного выполнения он получает предоставленный маркер напрямую.
При сбое вычислений запрашивается отмена для своих братьев и сестер. Операции должны наблюдать за их маркерами для сотрудничества. Если сбой нескольких вычислений, одно исключение распространяется; Не зависят от того, какой сбой выигрывает.
| Function | Фигура подписи |
|---|---|
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> |
Функции Async потоком маркера внешней отмены рабочего процесса. Существующий Async.Parallel (включая его параметр ограничения параллелизма) и Async.Sequential остается доступным. Варианты Do предоставляют результат, unit если требуется только завершение. Ограничение параллелизма не является ограничением скорости: быстрые операции по-прежнему могут создавать много запросов в секунду.
Преобразование результатов и восстановление после сбоев
Модули Microsoft.FSharp.Control.Asyncи ValueTask модули Taskпредоставляют эти квалифицированные функции.
M<'T> в столбце фигуры соответствует соответствующему типу вычислений, а не сокращению типа F#.
| Квалифицированные функции | 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>; обязательный аргумент явного типа ввода. |
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> |
Например, сопоставляйте содержимое файла с длиной, а затем представляет сбой чтения в виде Result:
open System.IO
open System.Threading
let fileLength (path: string) (ct: CancellationToken) =
File.ReadAllTextAsync(path, ct)
|> Task.map String.length
|> Task.catch
Файл, Report 1 содержащий данные Ok 8. Отсутствующий файл предоставляет Error содержащий объект FileNotFoundException. Чтобы отменить успешное значение, а не преобразовать его, укажите тип входных данных при вызове ignore:
let completion: System.Threading.Tasks.Task<unit> =
Task.result 42 |> Task.ignore<int>
catchWith предоставляет значение замены для сбоя без отмены; он не выполняет еще одно асинхронное вычисление.
catch возвращает Ok или Error. Отмена не преобразуется в значение ошибки или передается обработчику восстановления.
Task.empty
Task<unit>— это не универсальный Task.CompletedTaskобъект.
В отличие от нижнего регистра Async.catch, существующие Async.Catch возвращается Choice. Восстановление обрабатывает сбои предоставленных вычислений, а не синхронные исключения, создаваемые перед вызовом. Асинхронная синхронизация остается отложенной; задачи остаются готовыми.
Доступность ValueTask и библиотеки
Для API ValueTask требуется netstandard2.1 или net10.0 сборка FSharp.Core 11. См. раздел "Основной целевой объект".
Обратите внимание на контракт ValueTask с одним потреблением: потребляйте каждое значение один раз, а не через отдельные ожидания или конвейеры. Для повторяющихся ожиданий вызов Task.ofValueTask один раз и повторное использование только результирующей задачи.