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、 ValueTask<'T>、タスクに似たファクトリ オーバーロード。 |
Task.startAsyncImmediate |
CancellationToken -> Async<'T> -> Task<'T> |
Async.RunSynchronouslyImmediate |
Async<'T> * ?cancellationToken: CancellationToken -> 'T |
Async.RunSynchronouslyImmediate は、フォアグラウンド スレッド上の Async.RunSynchronously とは異なり、呼び出し元スレッドで開始され、完了のためにブロックされます。 タイムアウト パラメーターはありません。 UI と要求スレッドで非同期コンポジションを優先します。
非同期ワークフローをタスクとして公開する
上記のファイル読み取りワークフローをタスク ベースの呼び出し元に提供するには、キャンセル トークンを受け入れ、 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 は、計算の最大で正の上限を同時に開始し、結果を入力順に返します。 それ以外の場合、開始順序と完了順序は指定されていません。 コンカレンシーが 1 より大きい場合、各ファクトリは、兄弟障害を通知するリンクされたトークンを受け取ります。シーケンシャル実行の場合は、指定されたトークンを直接受け取ります。
1 つの計算エラーが発生すると、その兄弟に対してキャンセルが要求されます。 操作は、連携するためにトークンを観察する必要があります。 複数の計算が失敗した場合、1 つの例外が伝達されます。どの障害が優先するかに依存しません。
| 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結果を公開します。 コンカレンシー制限はレート制限ではありません。高速操作では、1 秒あたりに多数の要求を生成できます。
結果を変換し、障害から回復する
Microsoft.FSharp.Control.Async、Task、およびValueTaskモジュールは、これらの修飾された関数を公開します。
M<'T> 図形の列では、F# 型の省略形ではなく、対応する計算型を表します。
| 修飾関数 | 形状 |
|---|---|
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を提供します。 見つからないファイルは、FileNotFoundExceptionを含むErrorを提供します。 変換ではなく成功した値を破棄するには、 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 とライブラリの可用性
ValueTask API には、FSharp.Core 11 の netstandard2.1 または net10.0 ビルドが必要です。
コア ターゲットの選択を参照してください。
ValueTask の単一消費コントラクトを確認します。個別の待機またはパイプラインではなく、各値を 1 回使用します。 繰り返し待機する場合は、 Task.ofValueTask を 1 回呼び出し、結果のタスクのみを再利用します。
参照
.NET