异步 – 如何使用回调从C#方法创建F#异步?
假设我有一些C#代码需要回调:
void DoSomething(Action<string> callback); 现在,我想在F#中使用它,但将其包装在异步中.我该怎么做? // 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是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 在这里,我的功能很有趣(succ,cancl) – > succ 5已经确定它已成功完成,并调用succ continuation将其计算结果传递给下一步. 在您的情况下,函数DoSomething仅表示三种情况中的一种 – 即“成功完成时该怎么做”.一旦你进入回调,这意味着无论DoSomething做了什么,都已成功完成.那时你需要调用succ continuation: let doSometingAsync = Async.FromContinuations( fun (succ,cancl) -> Tasks.DoSomething( fun res -> succ res ) ) 当然,你可以避免嵌套的lambda-expression fun res – > succ res通过将succ直接传递给DoSomething作为回调.不幸的是,您必须明确指定要用于包装它的Action类型,这会抵消其优势: let doSometingAsync = Async.FromContinuations( fun (succ,cancl) -> Tasks.DoSomething( System.Action<string> succ ) ) 顺便说一句,请注意,这立即在DoSomething的API中发现了一个漏洞:它忽略了错误情况.如果DoSomething无法做任何意图,会发生什么?您无法了解它,整个异步工作流程将会挂起.或者,更糟糕的是:进程将立即退出(取决于崩溃的发生方式). 如果您对DoSomething有任何控制权,我建议您解决此问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |