假设我有一个频道out (chan)
。我需要获取放入通道的值并添加它们。值的数量未确定(因此不能使用带有(<! out)
的结束情况的传统循环)并且来自外部IO。我使用固定的timeout
和alts!
,但这似乎不是解决问题的最佳方法。到目前为止,我已经得到了以下内容(我从https://gist.github.com/schaueho/5726a96641693dce3e47获得)
(go-loop
[[v ch] (alts! [out (timeout 1000)])
acc 0]
(if-not v
(do (close! out)
(deliver p acc))
(do
(>! task-ch (as/progress-tick))
(recur (alts! [out (timeout 1000)]) (+ acc v)))))
我遇到的问题是1000的超时有时是不够的,导致go-loop过早退出(因为完成IO操作可能需要1000多秒才能完成并将val放入{{ 1}}频道)。我不认为增加超时值是一个好主意,因为它可能会让我等待超过必要的时间。
保证所有来自out通道的读取并从循环中正确退出的最佳方法是什么?
更新
为什么我使用超时?
因为放入通道的值的数量不固定;这意味着,我无法创建退出案例。如果没有退出情况,那么go-loop将默认等待(out
)等待放入通道中的值。如果你有一个没有超时的解决方案,那真的很棒。
我怎么知道我读过最后一个值? 我不。那就是问题所在。这就是我使用超时和等待的原因!退出循环。
你想做什么结果? 现在简单补充一下。但是,这不是重要的一点。
更新最终结果:
我找到了一种方法来获取我要处理的值的数量。所以我修改了我的逻辑以利用它。我还是要使用超时和alts!防止任何锁定。
(<! out)
答案 0 :(得分:2)
我认为你的设计中的问题有点高,而不是特定于核心的异步:
一方面,你有一个未确定的数值来自一个频道 - 可能有0,可能有10,可能有1,000,000。
另一方面,您想要阅读所有,进行一些计算然后返回。这是不可能的 - 除非有其他信号可以用来说“我想我现在已经完成了”。
如果该信号是值的时间,那么使用alts!
的方法是正确的,尽管我相信代码可以简化一点。
更新:您是否可以访问“上游”IO?当IO操作完成时,你可以将一个标记值(例如::closed
)放到通道中吗?
答案 1 :(得分:2)
最好的&#39;方法是等待来自out的特殊批量结束消息或由发送者关闭以标记输入的结束。
无论哪种方式,解决方案都由发件人传达有关输入的信息。