Чтобы ответить на первую часть вопроса - если вам нужно выполнить некоторую работу по очистке, вы можете просто поместить ее в finally
, и она будет вызвана, когда рабочий процесс отменяется. Например:
let work =
async {
try
printfn "first work"
do! Async.Sleep 1000
printfn "second work"
finally
printfn "cleanup" }
Допустим, вы запустили это с помощью Async.Start
, подождите 500 мс, а затем отмените вычисление:
let cts = new System.Threading.CancellationTokenSource()
Async.Start(work, cts.Token)
System.Threading.Thread.Sleep(500)
cts.Cancel()
Вывод будет "первая работа, очистка". Как видите, при отмене вычислений будут выполняться все предложения finally
.
Чтобы ответить на вторую часть вопроса - если вам нужно дождаться завершения работы, вы можете использовать RunSynchronously
(но тогда, возможно, вам на самом деле не нужны асинхронные рабочие процессы, если вы все равно блокируете ...) .
Следующее запускает фоновый процесс, который отменяет основную работу через 500 мс, а затем синхронно начинает основную работу:
let cts = new System.Threading.CancellationTokenSource()
async {
do! Async.Sleep(500)
cts.Cancel() } |> Async.Start
try Async.RunSynchronously(work, cancellationToken=cts.Token)
with :? System.OperationCanceledException -> ()
printfn "completed"
Это печатает «первая работа, очистка, завершена» - как вы можете видеть, вызов RunSynchronously
был заблокирован, пока работа не была отменена.