the*_*onk 11 f# asynchronous functional-programming
您可以使用哪些不同的技术在F#中创建Async <'T>的实例?
我看到Web客户端/请求和文件流有很多扩展方法,但是如果我想编写自己的异步计算提供程序,我将如何编写AsyncDoSomething同步DoSomething函数的那些版本?
我知道,你可以使用相同签名的委托来包装原有的功能,然后用Async.FromBeginEnd对BeginInvoke和EndInvoke方法:
open System
let del : Func<int> = new Func<int>(fun () -> 42)
let delAsync = async {
let! res = Async.FromBeginEnd(del.BeginInvoke, del.EndInvoke)
printfn "result was %d" res
}
Async.Start delAsync
Run Code Online (Sandbox Code Playgroud)
但这感觉有点强迫,它似乎不是'F#方式',因为你必须使用在C#或VB中定义的代理(其中有很多System.Action和System.Func变体可供选择)因为F#代表不要支持BeginInvoke和EndInvoke方法.
有没有人有一个列表,你可以在F#中编写同步函数的异步版本的不同方法?
提前谢谢了!
从文档Async,所有AwaitXXX和FromXXX方法.但最常见的方法是使用异步工作流程.然而,正如Mauricio评论的那样,用任意代码包装async { }并不总是有益的.
这里有一些代码来证明这一点.
open System.IO
let BUF_SIZE = 1 <<< 16 //64KB
let readFile f (stream:Stream) =
let buf = Array.zeroCreate BUF_SIZE
let rec read p =
async {
let! n = f stream buf
match n with
| 0 -> ()
| _ -> return! read (p + n)
}
read 0
let fakeAsyncReadFile s = readFile (fun stream buf ->
async { return stream.Read(buf, 0, buf.Length) }) s
let realAsyncReadFile s = readFile (fun stream buf ->
stream.AsyncRead(buf, 0, buf.Length)) s
let files = [@"C:\big_file_1"; @"C:\big_file_2"]
let readWith f =
let streams = Seq.map File.OpenRead files
try Seq.map f streams |> Async.Parallel |> Async.RunSynchronously |> ignore
finally streams |> Seq.iter (fun s -> s.Close())
readWith fakeAsyncReadFile //Real: 00:00:34.190, CPU: 00:00:03.166, GC gen0: 4, gen1: 2, gen2: 1
readWith realAsyncReadFile //Real: 00:00:05.101, CPU: 00:00:16.957, GC gen0: 31, gen1: 1, gen2: 0
Run Code Online (Sandbox Code Playgroud)
结束语同步Stream.Read与async { }产量没有明显的好处.异步工作流主要是链接异步操作的便捷方式.也就是说,它取决于具有良好编写的异步操作,以作为构建块.