Wis*_*yEh 3 f# asynchronous f#-async
有没有办法通过引入调度程序来限制/限制Async.Parallel?我希望并行执行Seq of Async <'a>,但不希望超过某个小时限制.
我可以使用每个Async <'a>检查的共享可变变量,但如果可能的话我想避免这种情况.
在封面下,该Async.Parallel操作使用标准的.NET线程池.所以,你可以配置线程池,但这可能不是一个好主意(你不应该阻塞线程池中的线程).
如果我想实现一些限制,我可能会为此创建一个F#代理.代理为您提供了一种协调并发的非常简单的方法 - 它可能比使用可变变量(为此目的)更多的代码,但它为您提供了一个很好的抽象:
// We can ask the agent to enqueue a new work item;
// and the agent sends itself a completed notification
type ThrottlingMessage =
| Enqueue of Async<unit>
| Completed
let throttlingAgent limit = MailboxProcessor.Start(fun inbox -> async {
// The agent body is not executing in parallel,
// so we can safely use mutable queue & counter
let queue = System.Collections.Generic.Queue<_>()
let running = ref 0
while true do
// Enqueue new work items or decrement the counter
// of how many tasks are running in the background
let! msg = inbox.Receive()
match msg with
| Completed -> decr running
| Enqueue w -> queue.Enqueue(w)
// If we have less than limit & there is some work to
// do, then start the work in the background!
while running.Value < limit && queue.Count > 0 do
let work = queue.Dequeue()
incr running
do!
// When the work completes, send 'Completed'
// back to the agent to free a slot
async { do! work
inbox.Post(Completed) }
|> Async.StartChild
|> Async.Ignore })
Run Code Online (Sandbox Code Playgroud)
要使用此功能,您可以创建具有指定限制的代理,然后调用Enqueue以添加您的工作项:
let w = throttlingAgent 5
for i in 0 .. 20 do
async { printfn "Starting %d" i
do! Async.Sleep(1000)
printfn "Done %d" i }
|> Enqueue
|> w.Post
Run Code Online (Sandbox Code Playgroud)
这解决了一个与你的问题有点不同的问题 - 但它应该显示方向(而不是Completed通知,你可能希望async在后台有一些每小时发送指定数量的"令牌").
| 归档时间: |
|
| 查看次数: |
366 次 |
| 最近记录: |