kno*_*cte 4 f# asynchronous computation-expression c#-to-f#
假设我想从F#调用这个C#函数:
public static class Foo {
public Bar Baz()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
问题是这个功能是CPU密集型的,我不想阻止它.不幸的是,C#库没有Task<Bar> BazAsync()过载.
然后我想通过创建一个调用它并返回(已经启动)的F#函数来自己提供异步版本Async<Bar>.也就是说,我不想用System.Threading.Task<Bar>.
我想我正在寻找的东西相当于Task<T>.Run()F#Async的做事方式.
我已经看过以下选项:
Async.StartAsTask - >处理C#ish任务类型.Async.Start和Async.StartImmediately- >收到Async<unit>不Async<T>是Async.StartChild我在寻找什么呢?如果是,那将是:
let BazWrapper() =
let asyncTask: Async<Bar> = async {
return Foo.Bar()
}
Async.StartChild asyncTask
Run Code Online (Sandbox Code Playgroud)
但是,如果以上是解决方案:
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...)
}
Run Code Online (Sandbox Code Playgroud)
当你在async计算表达式中时,let!关键字将"解包"一个Async<'Whatever>离开你的值为type 'Whatever.在调用的情况下Async.StartChild,'Whatever类型是具体的Async<'T>.
因此,如果要返回已启动的异步via Async.StartChild,则执行此操作的方法是:
let BazWrapper() =
let asyncTask: Async<Bar> = async {
return Foo.Bar()
}
async {
let! child = Async.StartChild asyncTask
return! child
}
Run Code Online (Sandbox Code Playgroud)
但是,我怀疑你会发现已经启动的异步对你来说并不像"冷"异步(还没有启动)那样有用,因为"冷"异步仍然可以与其他异步组合启动之前的异步任务.(这可以用于,例如,包装你的asyncs周围的日志.)所以,如果我正在为你的情况编写代码,我可能只是这样做:
let BazWrapper() =
async {
return Foo.Bar()
}
Run Code Online (Sandbox Code Playgroud)
现在BazWrapper()返回一个尚未启动的Async,Async.RunSynchronously如果您想立即使用该值,或者在其他async计算表达式中使用它,您可以启动它.
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |