考虑以下定义
let test =
Async.FromContinuations(
fun (cont,econt,ccont) ->
let rec inner () =
async {
do printfn "looping..."
do! Async.Sleep 1000
return! inner ()
}
Async.Start(inner ())
cont ())
假设我想尝试这样的计算
let cts = new CancellationTokenSource ()
Async.Start(test, cts.Token)
cts.Cancel()
这自然不会使内循环停止,因为我没有通过合适的取消令牌。有什么办法可以通过Async.FromContinuations获取外部取消令牌吗?我可以使用异步构建器和Async.CancellationToken重写它,但是我将失去将continuation传递给内部表达式的能力。
答案 0 :(得分:2)
let test =
async {
let! ct = Async.CancellationToken
return! Async.FromContinuations(
fun (cont,econt,ccont) ->
let rec inner () =
async {
do printfn "looping..."
do! Async.Sleep 1000
return! inner ()
}
Async.Start(inner (), cancellationToken = ct)
cont ())
}
let cts = new CancellationTokenSource ()
Async.Start(test, cts.Token)
cts.CancelAfter(1000)
答案 1 :(得分:2)
你能描述一下你想做什么吗?如果我正确理解您的代码,您希望在后台启动inner
循环函数,然后并行继续运行工作流的其余部分(使用cont()
调用)。
为此,您不需要Async.FromContinuations
。有一个函数正是这个,它还负责处理异常,取消令牌等。
我认为你可以像这样重写你的程序:
let test =
// The inner loop function from your example
let rec inner () = async {
do printfn "looping..."
do! Async.Sleep 1000
return! inner () }
async {
// Start the inner loop as a child async
let! _ = Async.StartChild(inner())
// ... continue doing other things in parllel if you wish
do printfn "main body running..." }
计算的启动和取消与以前一样:
let cts = new CancellationTokenSource ()
Async.Start(test, cts.Token)
// This will cancel the 'inner' loop as well
cts.Cancel()
如果使用Async.StartChild
来呼叫let!
,它将启动内部任务,向其传递取消令牌等。它会返回一个令牌,您可以稍后使用该令牌等待子任务完成,但是因为你没有这样做,我使用了_
模式。