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

标签 asynchronous f# c#-to-f# computation-expression

假设我想从 F# 调用这个 C# 函数:

public static class Foo {
    public Bar Baz()
    {
       ...
    }
}

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

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

我想我正在寻找的是相当于 Task<T>.Run()在 F# Async 处事方式中。

我已经看过以下选项:
  • 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
    

    但是,如果以上是解决方案:
  • 为什么大多数关于 F# 异步工作流的文档都没有提到 StartChild?
  • 为什么 BazWrapper 返回 Async<Async<Bar>>而不是 Async<Bar> ?
  • 最佳答案

    BazWrapper 返回 Async<Async<Bar>>因为这就是 StartChild 所做的:它需要一个 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 返回一个已经启动的异步。 ,这样做的方法是:
    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 中使用它计算表达式。

    关于asynchronous - 从 C# 调用非异步 Func<T> 返回 F# 函数中的启动 Async<T>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49463852/

    相关文章:

    javascript - 并行运行异步代码

    javascript - 访问通过启动异步请求的工厂初始化的变量

    f# - 如何简化 F# 数组中不存在于另一个数组中的元素的筛选?

    c# - 类层次结构定义 VS(自动)生成的导航属性

    wpf - WPF异步验证的最佳做法?

    c# - 异步方法在当前线程(主线程)启动AsyncCallback

    performance - F# 处理复杂键(如数据结构中的 int*int*int)比 Ocaml 慢得多

    F#:有些、无或异常(exception)?

    c# - 在 F# 中,具有强制构造函数参数的对象初始化程序语法是什么?

    f# 允许 cors web api