如何将FSharpx TaskBuilder与带有参数的函数一起使用 [英] How to use FSharpx TaskBuilder with functions taking parameters
问题描述
我最近一直在使用 FSharpx库进行编程,尤其是使用其 TaskBuilder 。现在,我想知道是否应该定义一个带有参数并带有结果的函数。例如
I have been lately programming with the FSharpx library and especially its TaskBuilder. Now I wonder if it should be possible to define a function which takes parameters and takes a result. Such as
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
| _ -> ()
看着源代码,我看到了运行期望函数不带任何参数并返回 Task< ;'a>
。 FSharpx TaskTests
Looking at the source code I see run expects a function taking no parameters and returning a Task<'a>
. There doesn't look like being examples on FSharpx TaskTests either.
如果有人可以建议我如何使用FSharpx来实现这样的方案,或者不应该使用类似的库,我将不胜感激
I'd appreciate if someone could advice how should I get a scenario like this going with FSharpx or if one isn't supposed to use the library like this for a reason I haven't quite grasped as of yet.
< edit:,我认为我可以将doTask包装如下:
<edit: I believe I could wrap doTask as follows
wrapperDoTask() = doTask(101)
match FSharpx.Task.run wrapperDoTask with
| _ -> ()
这可能有用。我目前没有使用编译器,因此有点麻烦。有人对任何方向都有意见吗?还是我只是回答自己的问题? :)
And it might work. I'm not with a compiler currently, so this is a bit of a handwaving. Does anyone have an opinion on any direction or did I just answer my own question? :)
< edit2:
我想我需要根据 MisterMetaphor的答案。我认为尤其是他的 P.S。
提供了很好的信息。我使用FSharpx TaskBuilder与C#互操作,如前所述,其中的任务已作为 hot 返回(已经有些例外),并且已经在运行。这与我最近的问题有关相对于调度程序,将并与 Orleans (我会添加一些标签来增强上下文,也许其他人也在考虑这些。)
<edit2:
I think I need to edit this one more time based on MisterMetaphor's answer. Especially his P.S.
, I think, was well informing. I use FSharpx TaskBuilder to interop with C#, in which, as noted, tasks are returned as hot (with some minor exceptions), already running. This is in connection with my recent question Translating async-await C# code to F# with respect to the scheduler and in relation Orleans (I'll add some tags to beef up the context, maybe someone else is pondering these too).
用C#术语思考时,我试图实现的目标是等待返回任务结果,但不会阻塞。我追求的行为尤其是 await
而不是 .Result
的行为。例如,可以从
When thinking in C# terms, what I try to achieve is to await the task result before returning, but without blocking. The behaviour I'm after is especially of that of await
not .Result
. The difference can be read, for instance, from
- Await, and UI, and deadlocks! Oh my!
- Don't Block on Async Code.
尝试思考哪个上下文,调度程序或行为或对于C#而言,发生的事情对我来说有些模糊。不幸的是,在互操作方面,我似乎无法忽略所有细节。 :)
Trying to think which context or scheduler or behavior or something is going on in terms of C# is somewhat fuzzy for me. Unfortunatelly it looks like I can't ignore all the details when it comes to interop. :)
推荐答案
仅当您需要使用 Task.run
时,想在当前线程上同步等待任务完成。它只需要一个参数,您可以将该参数视为任务工厂,即创建 Task< _>
的方法。与 Async< __>
不同, Task< __>
一经创建便开始运行。
You need to use Task.run
only if you want to wait for the task completion synchronously on the current thread. It takes a single parameter and you can consider that parameter a task factory -- i.e. a means to create a Task<_>
. Unlike Async<_>
, the Task<_>
starts running as soon as it is created. That is not always a desirable behavior.
使用(doTask 101)。您可以达到类似的结果(阻塞等待任务完成)。Result
,但是我认为 Task.run
对于F#来说更惯用了,因为它使用了 Result
返回类型表示发生错误而不是引发异常。视情况而定,这可能会更好,但根据我的经验,在较简单的情况下,特殊结果类型比异常更容易组合。
You could achieve similar results (a blocking wait for task completion) with (doTask 101).Result
, but I think Task.run
is more idiomatic to F#, in a way that it uses a Result
return type to signal an error instead of raising an exception. It might be arguable which is better, depending on situation, but in my experience in simpler cases a special result type is more composable than exceptions.
这里的另一点是,您应该避免阻塞等待( Task.run
, .Wait()
, .Result
)。 (理想情况下,您只能在程序的顶层使用其中之一。)
Another point here is that you should avoid blocking waits (Task.run
, .Wait()
, .Result
) as much as you can. (Ideally, you'd have one of those only at the top level of your program.)
P.S如果这超出了问题的范围,但是您的 doTask
函数看起来很有趣。 任务{返回! Task.Factory.StartNew(...)}
等效于 Task.Factory.StartNew(...)
。您可能想做的是 task {返回参数+ 1}
。
P.S. This if out of scope of the question, but your doTask
function looks funny. task { return! Task.Factory.StartNew( ... ) }
is equivalent to Task.Factory.StartNew( ... )
. What you probably wanted to do is task { return parameter + 1 }
.
EDIT
因此,针对OP的问题编辑:)如果您需要C#中的 await
行为,则只需使用让! ...
。像这样:
So, in response to OP's question edit :) If you need the await
behavior from C#, you just need to use let! ...
. Like this:
task {
let! x = someTask 1 2 3
return x + 5
}
这篇关于如何将FSharpx TaskBuilder与带有参数的函数一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!