Ответ 1
Вы можете использовать ContinueWith:
let awaitTask (t: Task) = t.ContinueWith (fun t -> ()) |> Async.AwaitTask
Или AwaitIAsyncResult с бесконечным таймаутом:
let awaitTask (t: Task) = t |> Async.AwaitIAsyncResult |> Async.Ignore
Я пытаюсь использовать библиотеку С# в F #. В библиотеке широко используется async/wait. Я хочу использовать в рабочем процессе async { ... }
в F #.
Я вижу, что мы можем Async.AwaitTask
использовать async С# методы, возвращающие Task<T>
, но как насчет тех, кто возвращает plain 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
Update:
Библиотека FSharp.Core для F # 4.0 теперь включает перегрузку Async.AwaitTask
, которая принимает равную Task
. Если вы используете F # 4.0, вы должны использовать эту основную функцию вместо кода ниже.
Оригинальный ответ:
Если ваша задача может вызвать исключение, вы, вероятно, также захотите проверить это. например.
let awaitTask (task : Task) =
async {
do! task |> Async.AwaitIAsyncResult |> Async.Ignore
if task.IsFaulted then raise task.Exception
return ()
}
Обновление:
Библиотека FSharp.Core для F # 4.0 теперь включает перегрузку Async.AwaitTask, которая принимает простую задачу. Если вы используете F # 4.0, вам следует использовать эту базовую функцию вместо приведенного ниже кода.
Оригинальный ответ:
Мне очень понравилось предложение Эшли с использованием функциональной композиции. Кроме того, вы можете расширить модуль Async следующим образом:
module Async =
let AwaitTaskVoid : (Task -> Async<unit>) =
Async.AwaitIAsyncResult >> Async.Ignore
Затем он появляется в Intellisense вместе с Async.AwaitTask. Его можно использовать так:
do! Task.Delay delay |> Async.AwaitTaskVoid
Есть предложения по улучшению имени?
Чтобы правильно правильно распределять оба исключения и отменять, я думаю, вам нужно что-то вроде этого (частично на основе удаленного ответа Томаша Петржичека):
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)