<T> 从 C# 调用非异步 Func 返回 F# 函数中的异步启动<T>?



假设我想从f#,此c#函数:

打电话给
public static class Foo {
    public Bar Baz()
    {
       ...
    }
}

问题是此功能是CPU密集型的,我不想阻止它。不幸的是,C#库没有Task<Bar> BazAsync()超载。

然后,我想通过创建一个调用它并返回(已经启动(Async<Bar>的F#函数来自己提供异步版本。也就是说,我不想使用System.Threading.Task<Bar>

我猜我要寻找的是f#async做事方式中的 Task<T>.Run()

我已经查看了以下选项:

  • Async.StartAsTask->处理C#ISH任务类型。
  • Async.StartAsync.StartImmediately->接收Async<unit>不是Async<T>

Async.StartChild我要寻找什么?如果是,那将是:

let BazWrapper() =
    let asyncTask: Async<Bar> = async {
        return Foo.Bar()
    }
    Async.StartChild asyncTask

但是,如果以上是解决方案:

  1. 为什么大多数围绕f#async工作流的文档不提起启动孩子?
  2. 为什么BazWrapper返回Async<Async<Bar>>而不是Async<Bar>

bazwrapper返回 Async<Async<Bar>>,因为那是起始人的工作:它需要Async<'T>并返回Async<Async<'T>>。目的是在异步计算表达式中使用它,以便您可以启动多个"孩子"异步。来自async.start vs async.startchild示例代码的示例:

async {
    //(...async stuff...)
    for msg in msgs do 
        let! child = asyncSendMsg msg |> Async.StartChild
        ()
    //(...more async stuff...)
}

当您进入async计算表达式中时,let!关键字将"解开" Async<'Whatever>,使您拥有类型'Whatever的值。在调用Async.StartChild的情况下,'Whatever类型是Async<'T>

因此,如果您想通过Async.StartChild返回已经启动的 async,那么这样做的方法是:

let BazWrapper() =
    let asyncTask: Async<Bar> = async {
        return Foo.Bar()
    }
    async {
        let! child = Async.StartChild asyncTask
        return! child
    }

但是,我怀疑您会发现已经启动的异步对您不像"冷"异步(尚未开始(那样有用,因为"冷"异步仍然可以是启动之前,请与其他异步任务组成。(例如,这对于包裹在异步周围记录可能很有用。(因此,如果我为您的情况编写代码,我可能会简单地执行此操作:

let BazWrapper() =
    async {
        return Foo.Bar()
    }

和现在的bazwrapper((返回尚未启动的异步,如果您要立即使用该值,则可以使用Async.RunSynchronously启动,或者在其他async计算表达式中使用。

相关内容

  • 没有找到相关文章