Взаимодействие с асинхронными методами .NET

Последнее обновление: 15.12.2023

Плафторма .NET предоставляет множество различного асинхронного функционала для различных целей - для обращения к базам данных, к файлам, для отправки сетевых запросов и так далее. И в F# мы можем использовать весь этот функционал. Рассмотрим на примере статического асинхронного метода File.ReadAllTextAsync(), который считывает текст из файла и возвращает считанный текст.

Для примера определим в папке программы файл "hello.txt" с каким-нибудь текстом, например:

Hello F#
Hello Metanit.com

Для считывания этого файла определим следующую программу на F#:

open System.IO  // пространство имен, где определен класс File

async {
    let text = File.ReadAllTextAsync("hello.txt") |> Async.AwaitTask |> Async.RunSynchronously
    printfn "%s" text
} |> Async.Start

printfn "Program works"
printfn "Program ends"

Здесь в функцию File.ReadAllTextAsync() передается имя файла. Но эта функция возвращает не просто считанный текст, а объект Task<string> - некоторую задачу, которая выполнится в будущем и которая позволяет получить объект string - считанный текст. Поэтому ее результат (объект Task) передаем в функцию Async.AwaitTask. Функция Async.AwaitTask будет ожидать выполнения задачи Task и получит ее результат.

Функция Async.AwaitTask возвращает объект Async<'T> (в данном случае Async<'string>) где T - тип результата. Чтобы получить данные из Async, передаем результат функции Async.AwaitTask в функцию Async.RunSynchronously. Результат функции Async.RunSynchronously и будет представлять собственно считанные из файла данные.

После получения считанных данных выводим их на консоль. Консольный вывод:

Program works
Program ends
Hello F#
Hello Metanit.com

По консольному выводу видно, что блок async со считыванием файлов отработал асинхронно, без блокировки главного потока.

Но с помощью привязки let мы можем сократить код:

async {
    let! text = File.ReadAllTextAsync("hello.txt") |> Async.AwaitTask
    printfn "%s" text
} |> Async.Start

Блок task

Для упрощения работы с API, которые возвращают объекты Task в .NET, также можно использовать блок выражений task { ... }. Внутрь фигурных скобок помещается набор выражений, которые выполняют задачи Task. Так, перепишем предыдущий пример с использованием этого блока:

open System.IO

task {
    let! text = File.ReadAllTextAsync("hello.txt")
    printfn "%s" text
}

printfn "Program works"
printfn "Program ends"

Выражения в блоке task запускаются сразу после выполнения этого кода и выполняются в текущем потоке до тех пор, пока не встретися первая асинхронная операция (например, метод File.ReadAllTextAsync). Чтобы получить результат асинхронного метода применяется привязка let!

let! text = File.ReadAllTextAsync("hello.txt")
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850