2015-09-14 5 views
6

実行ブロックを停止するエレガントな方法はありますか?ClojureScript/core.asyncでgoブロックを停止するには?

(ns example 
    (:require-macros [cljs.core.async.macros :refer [go]]) 
    (:require  [cljs.core.async  :refer [<! timeout]])) 

(defn some-long-task [] 
    (go 
    (println "entering") 

    ; some complex long-running task (e.g. fetching something via network) 
    (<! (timeout 1000)) 
    (<! (timeout 1000)) 
    (<! (timeout 1000)) 
    (<! (timeout 1000)) 

    (println "leaving"))) 

; run the task 
(def task (some-long-task)) 

; later, realize we no longer need the result and want to cancel it 
; (stop! task) 
+0

'(close!task)' maybe? - Googleの最初の結果。 – birdspider

答えて

4

申し訳ありません(フラグを導入し、チェック/分岐を有するコードを汚染することなく)、これはcore.async今日では不可能です。 goブロックの作成から戻ってきたのは、ブロックの結果を実際のブロック自体に渡すことはできませんが、通常のチャネルです。

1

このようなタスクには、将来の予定と今後の予定を使用することができます。

(def f (future (while (not (Thread/interrupted)) (your-function ...)))) 
(future-cancel f) 
アーサーの答えで述べたように

Why do cancelled Clojure futures continue using CPU?

2

は、あなたがすぐにgoブロックを終了することはできませんが、あなたの例からあなたは(サブタスクを使用して)マルチフェーズ・タスクを示し、このようなアプローチはうまくいくかもしれません:

(defn task-processor 
    "Takes an initial state value and number of tasks (fns). Puts tasks 
    on a work queue channel and then executes them in a go-loop, with 
    each task passed the current state. A task's return value is used as 
    input for next task. When all tasks are processed or queue has been 
    closed, places current result/state onto a result channel. To allow 
    nil values, result is wrapped in a map: 

    {:value state :complete? true/false} 

    This fn returns a map of {:queue queue-chan :result result-chan}" 
    [init & tasks] 
    (assert (pos? (count tasks))) 
    (let [queue (chan) 
     result (chan)] 
    (async/onto-chan queue tasks) 
    (go-loop [state init, i 0] 
     (if-let [task (<! queue)] 
     (recur (task state) (inc i)) 
     (do (prn "task queue finished/terminated") 
      (>! result {:value state :complete? (== i (count tasks))})))) 
    {:queue queue 
    :result result})) 

(defn dummy-task [x] (prn :task x) (Thread/sleep 1000) (inc x)) 

;; kick of tasks 
(def proc (apply task-processor 0 (repeat 100 dummy-task))) 

;; result handler 
(go 
    (let [res (<! (:result proc))] 
    (prn :final-result res))) 

;; to stop the queue after current task is complete 
;; in this example it might take up to an additional second 
;; for the terminated result to be delivered 
(close! (:queue proc)) 
関連する問題