gpt4 book ai didi

asynchronous - 如何从带有回调的 C# 方法创建 F# 异步?

转载 作者:行者123 更新时间:2023-12-04 13:56:42 26 4
gpt4 key购买 nike

假设我有一些需要回调的 C# 代码:

void DoSomething(Action<string> callback);

现在,我想在 F# 中使用它,但将其包装在 async 中.我该怎么办?
// Not real code
let doSomething = async {
let mutable result = null
new Action(fun x -> result <- x) |> Tasks.DoSomething
// Wait for result to be assigned
return result
}

例如,假设 DoSomething看起来像这样:
module Tasks

let DoSomething callback =
callback "Hello"
()

那么下面的输出应该是 "Hello" :
let wrappedDoSomething = async {
// Call DoSomething somehow
}

[<EntryPoint>]
let main argv =
async {
let! resultOfDoSomething = wrappedDoSomething
Console.WriteLine resultOfDoSomething
return ()
} |> Async.RunSynchronously
0

最佳答案

函数Async.FromContinuations可以说是异步的“最低级别”。所有其他异步组合器都可以用它来表示。

从某种意义上说,它是最低级别,它直接编码了异步计算的本质——在三种可能的情况下要做什么的知识:(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 )
)

当然,您可以避免嵌套的 lambda 表达式 fun res -> succ res通过 succ直接进入 DoSomething作为回调。不幸的是,您必须明确指定 Action 的类型。用于包装它,这否定了优势:
let doSometingAsync = 
Async.FromContinuations( fun (succ, err, cancl) ->
Tasks.DoSomething( System.Action<string> succ )
)

顺便说一句,请注意,这立即发现了 DoSomething 中的一个漏洞。的 API:它忽略错误情况。如果 DoSomething 会发生什么?没有做它应该做的事情?你不可能知道它,整个异步工作流程就会挂起。或者,更糟糕的是:进程将立即退出(取决于崩溃的发生方式)。

如果您对 DoSomething 有任何控制权,我建议你解决这个问题。

关于asynchronous - 如何从带有回调的 C# 方法创建 F# 异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50782719/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com