F#でC#ライブラリを使用しようとしています。ライブラリはasync/awaitを多用します。 F#のasync { ... }
ワークフロー内で使用したい。
Async.AwaitTask
を返す非同期C#メソッドでTask<T>
できるようですが、プレーンなTask
を返すメソッドはどうでしょうか。
おそらく、これらをAsync<unit>
に変換したり、Task
をTask<unit>
に変換して、Async.AwaitTask
で動作するようにするヘルパーはありますか?
あなたはContinueWithを使うことができます:
let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> Async.AwaitTask
または、無限タイムアウトのAwaitIAsyncResult:
let awaitTask (t: Task) = t |> Async.AwaitIAsyncResult |> Async.Ignore
更新:
F#4.0のFSharp.Coreライブラリには、プレーンなTask
を受け入れるAsync.AwaitTask
オーバーロードが含まれるようになりました。 F#4.0を使用している場合は、以下のコードの代わりにこのコア関数を使用する必要があります。
元の回答:
タスクが例外をスローする可能性がある場合は、おそらくこれも確認する必要があります。例えば.
let awaitTask (task : Task) =
async {
do! task |> Async.AwaitIAsyncResult |> Async.Ignore
if task.IsFaulted then raise task.Exception
return ()
}
更新:
F#4.0のFSharp.Coreライブラリに、プレーンタスクを受け入れるAsync.AwaitTaskオーバーロードが含まれるようになりました。 F#4.0を使用している場合は、以下のコードの代わりにこのコア関数を使用する必要があります。
元の回答:
関数合成を使ったアシュリーの提案が本当に気に入りました。さらに、次のように非同期モジュールを拡張できます。
module Async =
let AwaitTaskVoid : (Task -> Async<unit>) =
Async.AwaitIAsyncResult >> Async.Ignore
次に、Async.AwaitTaskとともにIntellisenseに表示されます。これは次のように使用できます。
do! Task.Delay delay |> Async.AwaitTaskVoid
より良い名前の提案はありますか?
例外とキャンセルの両方を適切に伝播するには、I think次のようなものが必要です(TomášPetříčekによる削除された回答に部分的に基づいています):
module Async =
let AwaitVoidTask (task : Task) : Async<unit> =
Async.FromContinuations(fun (cont, econt, ccont) ->
task.ContinueWith(fun task ->
if task.IsFaulted then econt task.Exception
Elif task.IsCanceled then ccont (OperationCanceledException())
else cont ()) |> ignore)