我想实现我从唐赛姆的博客阅读模式
(Qazxswpoi)
这表明,有从利用异步I / O大量提高性能的机会。目前我正在试图采取这一“工程”的一种方式,用Array.Parallel.Map一段代码,看看我是否能使用Async.Parallel某种方式达到同样的效果,但我真的不明白Async.Parallel,并不能得到任何工作。
我有一段代码(下面简化为说明这一点),其成功地检索数据的数组,一个CUSIP。 (A价格序列,例如)
https://blogs.msdn.microsoft.com/dsyme/2010/01/09/async-and-parallel-design-patterns-in-f-parallelizing-cpu-and-io-computations/
因此,这种方法contructs数组的数组,通过使在互联网上我的数据供应商每只股票的连接(这可能是多达3000),并返回我阵列(1元股票的阵列,具有价格序列的每个一)。我固然不明白那张Array.Parallel.map下,但我想如果这是那里的引擎盖下的资源浪费的情形,它实际上可以使用异步I / O更快?因此,测试了这一点,我试图让使用异步操作这个功能,我认为下面的功能使用如下的URL在Don赛姆的文章的模式,但它不会与“放!”编译。
let getStockData cusip =
let D = DataProvider()
let arr = D.GetPriceSeries(cusip)
return arr
let data = Array.Parallel.map (fun x -> getStockData x) stockCusips
我得到的错误是:这表达预计将有型异步<'一>但这里的类型为OBJ
它编译罚款与“让”,而不是“让!”,但我以为整点是,你需要的感叹号,以便命令不阻塞线程运行。
因此,第一个真正的问题是,这有什么错我的语法上面,在getStockDataAsync,然后在一个较高的水平,任何人都可以提供关于台异步I / O,以及是否我已经提出会从中受益的情况下一些额外的洞察力,使之成为可能多少,比Array.Parallel.map快得多?非常感谢。
F#异步工作流,可以实现异步计算,然而,F#使得通常的计算和异步计算之间的区别。这种差异是由类型系统追踪。例如该下载网页,是同步的有型let getStockDataAsync cusip =
async { let D = DataProvider()
let! arr = D.GetData(cusip)
return arr
}
(以URL并返回HTML)的方法,但做同样的事情异步有型string -> string
的方法。在string -> Async<string>
块,你可以使用async
调用异步操作,但所有其他(标准同步)方法必须使用let!
被调用。现在,你的榜样的问题是,let
操作是普通的同步方法,所以你不能用GetData
调用它。
在典型的F#的情况下,如果你想使let!
成员异步的,你需要使用异步工作流程来实现它,所以你还需要将其包装在GetData
块。在某些时候,你会到达一个位置,你真的需要异步运行一些基本操作(例如,从网站上下载数据)。 F#提供了可以从async
块使用async
调用诸如let!
(这是AsyncGetResponse
方法的异步版本)几个原始异步操作。所以,在你GetResponse
方法,你就如写的是这样的:
GetData
总结是,你需要确定一些基本的异步操作(如等待Web服务器或文件系统),在这一点上使用原始的异步操作,敷在let GetData (url:string) = async {
let req = WebRequest.Create(url)
let! rsp = req.AsyncGetResponse()
use stream = rsp.GetResponseStream()
use reader = new System.IO.StreamReader(stream)
let html = reader.AsyncReadToEnd()
return CalculateResult(html) }
块使用这些操作的所有代码。如果有可以异步运行,没有原始的操作,那么你的代码是CPU绑定的,你可以只使用async
。
我希望这可以帮助您了解F#异步工作流程是如何工作的。欲了解更多信息,例如,您可以看看Parallel.map
,一系列关于Don Syme's blog post,还是我asynchronous programming by Robert Pickering。
@Tomas已经有一个伟大的答案。我只想说,除了一对夫妇位。
为F#异步操作的成语是命名与“异步”前缀的方法(F# web cast,不AsyncFoo
;后者是已被其他.NET技术成语)。所以,你的功能应该是FooAsync
和getStockData
。
内部的异步工作流程,只要您使用asyncGetStockData
代替let!
或let
代替do!
的,右边的东西应该有类型do
而不是Async<T>
。基本上你需要为了在工作流程的这一点“走出去异步”现有的异步计算。每个T
本身将是要么其他一些Async<T>
工作流程,否则异步“原始”。的原语的F#库经由async{...}
或其使得能够限定开始计算,注册一个I / O回调,释放线程,然后重新启动计算的低级别的细节时获取调用回Async.FromBeginEnd
定义的或在用户代码创建。所以,你必须“垂直”异步一路下跌到一些真正的,异步I / O基元以获得异步I / O的全部好处。