我最近使用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#考虑哪个上下文或调度程序或行为或某事正在发生,这对我来说有点模糊。不幸的是,当谈到互操作时,我似乎无法忽略所有细节。 :)
答案 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
}