如何构建类似 setInterval 的任务?

How to build a setInterval-like task?

这是我的想法

task=@task begin
while true
    sleep(1)
    foo()
    if should_end
        # ?
    end
end
end

但是有一些问题

  1. 除了使用 global should_end 之外,还有其他简单的联系方式吗?
  2. 如何从表达式内部结束任务?

虽然实现这样的东西可能是一个很好的练习,但请注意 Timers are in the standard library and they are similar to the JS functions you may be used to because Julia and Node.js both use libuv internally. Whether you use Node.js setInterval or Timeout, or Julia Timer eventually uv_timer_start 被调用(尽管定时器的创建和 low-level 管理在各自的运行时是不同的)。

要回答您的 第二个 问题,您只需 breakif 表达式中:

julia> should_end = false
false

julia> task = @task begin
           while true
               sleep(1)
               if should_end
                   break
               end
           end
           "Tasks can return a value"
       end
Task (runnable) @0x00007fca1c9c3990

julia> schedule(task)
Task (runnable) @0x00007fca1c9c3990

julia> task
Task (runnable) @0x00007fca1c9c3990

julia> should_end = true;sleep(1)

julia> task
Task (done) @0x00007fca1c9c3990

julia> fetch(task)
"Tasks can return a value"

至于第一个问题,Julia文档中有很多信息,例如Asynchronous Programming section. As is described there, Channels 可用于任务之间的通信(如果合适)。请注意 should_end 不一定是 global。任务包装一个函数,该函数可以捕获封闭范围内的变量(@task begin a = 1 end 实际上只是 Task(() -> begin a = 1 end).

这是一个使用 TimerChannel 将数据发送到任务的简短示例:

function pinger(n)
    ping() = parse(Float64, match(r"time=(.*) ms", read(`ping -c 1 8.8.8.8`, String))[1])
    ch = Channel{Float64}(0)

    pinger = Timer(0.0; interval=1.0) do timer
        put!(ch, ping())
    end

    summer = @task begin
        total = 0.0
        count = 0
        while count < n
            total += take!(ch)
            count += 1
        end
        total / count
    end
    schedule(summer)
    fetch(summer)
end
julia> pinger(3)
19.5