Функция Async.FromContinuations является, так сказать, «самым низким уровнем» Async.Все другие асинхронные комбинаторы могут быть выражены в терминах этого.
Это самый низкий уровень в том смысле, что он непосредственно кодирует саму природу асинхронных вычислений - знание того, что делать в трех возможных случаях: (1) успешное завершение предыдущего шага вычисления, (2) сбой предыдущего шага вычисления и (3) отмена извне.Эти возможные случаи выражаются в виде трех аргументов типа функции функции, которую вы передаете Async.FromContinuations
.Например:
let returnFive =
Async.FromContinuations( fun (succ, err, cancl) ->
succ 5
)
async {
let! res = returnFive
printfn "%A" res // Prints "5"
}
|> Async.RunSynchronously
Здесь моя функция fun (succ, err, cancl) -> succ 5
решила, что она успешно выполнена, и вызывает продолжение succ
, чтобы передать результат вычисления на следующий шаг.
В вашем случае функция DoSomething
выражает только один из трех случаев - то есть «что делать при успешном завершении».Как только вы попадаете в обратный вызов, это означает, что все, что делал DoSomething
, завершилось успешно.Вот тогда вам нужно вызвать продолжение succ
:
let doSometingAsync =
Async.FromContinuations( fun (succ, err, cancl) ->
Tasks.DoSomething( fun res -> succ res )
)
Конечно, вы можете избежать вложенного лямбда-выражения fun res -> succ res
, передав succ
непосредственно в DoSomething
в качестве обратного вызова.К сожалению, вам придется явно указать, какой тип Action
использовать для его обертывания, что сводит на нет преимущество:
let doSometingAsync =
Async.FromContinuations( fun (succ, err, cancl) ->
Tasks.DoSomething( System.Action<string> succ )
)
Обратите внимание, что это сразу же обнаружило дыру вAPI DoSomething
: он игнорирует ошибку.Что произойдет, если DoSomething
не сможет сделать то, что должен был сделать?Вы не могли бы знать об этом, и весь асинхронный рабочий процесс просто зависнет.Или, что еще хуже: процесс завершится немедленно (в зависимости от того, как произойдет сбой).
Если у вас есть контроль над DoSomething
, я предлагаю вам решить эту проблему.