F# 异步取消定义原子计算

F# Async cancellation define atomic computations

我有以下情况:

                async {
                    let! result = props.onClick args
                    do someThingLikeShowToastMessageWithResult(result)
                    return result
                }

异步计算不是由我启动的,而是由我无法控制的库启动的,并且该库(正确地)将取消标记传递给最终的 StartImmediate 调用。

我如何以 'atomic' 的方式编写此异步计算?例如,如果包含异步计算被取消,它要么在此之前或之后取消,但不在此计算内。

这背后的意图是,一旦调用了 onClick 异步计算(这是一个保存数据的服务器调用),数据就被发送过来,服务器将保存它,除非出现其他错误。在此处取消只会导致取消通知用户服务器执行了他告诉它要做的事情。

编辑:我能想到的最好办法是用其他构造(例如 Task,或者在本例中是 Promise,因为它在 Fable 应用程序中)打破 Async CE:

                async {
                    let ct = new System.Threading.CancellationTokenSource()
                    let computation =
                        async {
                            let! result = props.onClick args
                            do someThingLikeShowToastMessageWithResult(result)
                            return result
                        }
                    let atomicComputation =
                        Async.StartAsPromise(computation, token = ct.Token)
                        |> Async.AwaitPromise
                    return! atomicComputation
                }

看起来很复杂,我还不确定所有意想不到的后果。

我也想不出更好的方法,我唯一能做的就是添加一些辅助函数,让你的意图更清楚一些。

module Async =
    let runUncancellable a =
        async {
            let ct = new System.Threading.CancellationTokenSource()
            return! Async.StartAsTask(a, cancellationToken = ct.Token) |> Async.AwaitTask
        }

用法:

let someAsyncOperation : Async<int> =
    failwith "NYI"
    
async {
    let! a = someAsyncOperation
    let! b = runUncancellable someAsyncOperation
    let! c = someAsyncOperation
    return a + b + c
}