如何使用带有参数的函数的FSharpx TaskBuilder

时间:2014-07-27 12:58:18

标签: f# c#-to-f# orleans

我最近使用FSharpx library进行编程,尤其是TaskBuilder。现在我想知道是否应该可以定义一个接受参数并获取结果的函数。如

 let doTask(parameter:int) =
     let task = TaskBuilder(scheduler = TaskScheduler.Current)        
     task {
         return! Task.Factory.StartNew(fun() -> parameter + 1)
     } 

 match FSharpx.Task.run doTask(1) with
 | _ -> ()

查看源代码,我看到run期望函数不带参数并返回Task<'a>。看起来不像是FSharpx TaskTests上的例子。

我很感激,如果有人可以建议我如何使用FSharpx获得这样的场景,或者如果不应该使用这样的库,原因我还没有完全掌握。

&lt; edit:我相信我可以将doTask包装成如下

 wrapperDoTask() = doTask(101)
 match FSharpx.Task.run wrapperDoTask with
 | _ -> ()

它可能会奏效。我目前没有使用编译器,所以这有点像手工操作。有没有人对任何方向有意见,或者我只是回答我自己的问题? :)

&LT; EDIT2: 我想我需要根据MisterMetaphor's回答再次编辑这个。我认为,特别是他的P.S.很有见效。我使用FSharpx TaskBuilder与C#互操作,其中,如上所述,任务以 hot (有一些小的例外)返回,已经在运行。这与我最近的问题Translating async-await C# code to F# with respect to the scheduler和关系Orleans有关(我会添加一些标签来强化上下文,也许其他人也在考虑这些问题)。

在考虑C#术语时,我尝试实现的是在返回之前等待任务结果,但没有阻塞。我所追求的行为特别是await而非.Result的行为。例如,可以从

中读取差异

尝试根据C#考虑哪个上下文或调度程序或行为或某事正在发生,这对我来说有点模糊。不幸的是,当谈到互操作时,我似乎无法忽略所有细节。 :)

1 个答案:

答案 0 :(得分:2)

仅当您要在当前线程上同步等待任务完成时,才需要使用Task.run。它只需要一个参数,您可以将该参数视为任务工厂 - 即创建Task<_>的方法。与Async<_>不同,Task<_>会在创建后立即开始运行。这并不总是一种理想的行为。

您可以使用(doTask 101).Result获得类似的结果(阻止等待任务完成),但我认为Task.run对于F#更为惯用,因为它使用Result返回键入以表示错误而不是引发异常。可能有争议哪个更好,取决于情况,但根据我在更简单的情况下的经验,特殊结果类型比例外更容易组合。

此处的另一点是,您应该尽可能避免阻止等待(Task.run.Wait().Result)。 (理想情况下,您只能在程序的顶层使用其中一个。)

P.S。如果超出问题范围,但您的doTask功能看起来很有趣。 task { return! Task.Factory.StartNew( ... ) }相当于Task.Factory.StartNew( ... )。您可能想要做的是task { return parameter + 1 }

修改

所以,回应OP的问题编辑:)如果你需要来自C#的await行为,你只需要使用let! ...。像这样:

task {
    let! x = someTask 1 2 3
    return x + 5
}