【发布时间】:2015-03-17 03:00:25
【问题描述】:
我正在使用 core.async 并行执行某些操作,然后使用 alts!! 等待一定数量的超时结果。
(ns c
(:require [clojure.core.async :as a]))
(defn async-call-on-vector [v]
(mapv (fn [n]
(a/go (a/<! (a/timeout n)) ; simulate long time work
n))
v))
(defn wait-result-with-timeout [chans num-to-get timeout]
(let [chans-count (count chans)
num-to-get (min num-to-get
chans-count)]
(if (empty? chans)
[]
(let [timeout (a/timeout timeout)]
(loop [result []
met 0]
(if (or (= (count result) num-to-get)
(= met chans-count)) ; all chan has been consumed
result
(let [[v c] (a/alts!! (conj chans timeout))]
(if (= c timeout)
result
(case v
nil (do (println "got nil") (recur result met)) ; close! on that channel
(recur (conj result v) (inc met)))))))))))
然后像这样调用:
user=> (-> [1 200 300 400 500] c/async-call-on-vector (c/wait-result-with-timeout 2 30))
这个表达式会打印出很多got nil。似乎 go 块返回的通道将在返回结果后关闭该通道。这将导致alts!! 在这种情况下返回 nil。但这对 CPU 很不友好,就像忙着等待一样。有没有办法避免这种情况?
我通过定义一个像 go 这样的宏来解决这个问题,但是返回一个不会在返回结果时关闭的通道。这是解决问题的正确方法吗?
【问题讨论】:
-
你看异步管道函数了吗?看起来非常相似 - github.com/clojure/core.async/blob/master/src/main/clojure/…
-
@edbond 好吧,用例不同,但是在我阅读库之后,我认为
merge适合我的需要,除了我必须用超时包装它。无论如何,谢谢。
标签: clojure core.async