簡體   English   中英

F# 異步:相當於 Boost asio 的鏈

[英]F# Async: equivalent of Boost asio's strands

Boost 的asio庫允許通過以下方式序列化異步代碼。 異步函數的處理程序(例如從 stream 讀取的函數)可能與strand相關聯。 一個鏈與一個“IO 上下文”相關聯。 一個 IO 上下文擁有一個線程池。 無論池中有多少線程,都可以保證不會有兩個與同一鏈關聯的處理程序同時運行。 例如,這使得實現 state 機器成為可能,就好像它是單線程的,其中該機器的所有處理程序都在私有鏈上序列化。

我一直在試圖弄清楚如何使用 F# 的Async來完成。 我找不到任何方法來確保所選的Async進程集永遠不會同時運行。 誰能建議如何做到這一點?

了解您嘗試實現的用例是什么會很有用。 我不認為 F# async有任何可以將 map 直接連接到 strands 的東西,您可能會使用不同的技術來實現可能都使用 strands 實現的不同事物。

例如,如果您關心從 stream 讀取數據,則 F# async塊允許您編寫異步但順序的代碼。 以下運行單個邏輯進程(當您使用let!等待時,可能會在線程池的線程之間移動它):

let readTest () = async { 
  let fs = File.OpenRead(@"C:\Temp\test.fs")
  let buffer = Array.zeroCreate 10
  let mutable read = 1
  while read <> 0 do
    let! r = fs.AsyncRead(buffer, 0, 10)
    printfn "Read: %A" buffer.[0 .. r-1]
    read <- r }

readTest() |> Async.Start

如果您想處理在沒有任何控制的情況下發生的事件(即基於推送而不是基於拉取),例如,當您無法要求系統讀取下一個數據緩沖區時,您可以使用MailboxProcessor序列化事件。 以下幾乎同時向代理發送兩條消息,但它們是按順序處理的,有 1 秒的延遲:

let agent = MailboxProcessor.Start(fun inbox -> async {
  while true do 
    let! msg = inbox.Receive()
    printfn "Got: %s" msg
    do! Async.Sleep(1000)
})

agent.Post("hello")
agent.Post("world")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM