如何将FSharpx TaskBuilder与带有参数的函数一起使用 [英] How to use FSharpx TaskBuilder with functions taking parameters

查看:97
本文介绍了如何将FSharpx TaskBuilder与带有参数的函数一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆