doupin5408 2016-03-14 05:01
浏览 21
已采纳

如何等待频道活动中的停顿触发某些事件?

I have a channel that will receive bursts of writes to it. I want to wait until a burst of sends on the channel have finished before triggering an action.

I have looked at this gist, however, it will send on the output every intervalif there is data in the buffer:

func debounceChannel(interval time.Duration, output chan int) chan int {
  input := make(chan int)

  go func() {
    var buffer int
    var ok bool

    // We do not start waiting for interval until called at least once
    buffer, ok = <-input 
    // If channel closed exit, we could also close output
    if !ok {
      return
    }

    // We start waiting for an interval
    for {
      select {
      case buffer, ok = <-input:
        // If channel closed exit, we could also close output
        if !ok {
          return
        }

      case <-time.After(interval):
        // Interval has passed and we have data, so send it
        output <- buffer
        // Wait for data again before starting waiting for an interval
        buffer, ok = <-input
        if !ok {
          return
        }
        // If channel is not closed we have more data and start waiting for interval
      }
    }
  }()

  return input
}

In my case, I want to wait until there is no longer any data being sent on the input channel for this burst before triggering or sending on the output.

How do I achieve this?

  • 写回答

2条回答 默认 最新

  • dougang1965 2016-03-14 06:38
    关注

    This is what I ended up implementing as my debouncer:

    func Debounce(lull time.Duration, in chan struct{}, out chan struct{}) {
    
        go func() {
    
            var last int64 = 0
    
            for {
                select {
                case <-in:
                    last = time.Now().Unix()
    
                case <-time.Tick(lull):
                    if last != 0 && time.Now().Unix() >= last+int64(lull.Seconds()) {
                        last = 0
                        out <- struct{}{}
                    }
                }
            }
        }()
    }
    

    It takes a lull time which is the duration where if we do not receive on the input, then we assume there is a break in the bursts of data. There are 2 channels, 1 input and 1 output. The bursts of data arrives on the input, and for each burst, we write to the output channel at the end of the burst.

    The implementation is extremely simplistic. I just store the current unix timestamp every time I receive from the input channel. Then, I have a ticker ticking with a duration of the lull time. All this does is check to see if we've exceeded the wait time for the last burst. If so, it resets last to 0 an emits an event on the output channel.

    Here's some code using the debounce function with a lull time of 2 seconds which sends random bursts on the input channel:

    func main() {
    
        out := make(chan struct{})
        in := make(chan struct{})
    
        Debounce(2*time.Second, in, out)
    
        // Generating bursts of input data
        go func(in chan struct{}) {
    
            for {
                select {
                case <-time.Tick(1 * time.Second):
                    in <- struct{}{}
    
                    fmt.Println("Sending!")
    
                    shouldSleep := rand.Intn(2)
                    if shouldSleep == 1 {
                        time.Sleep(5 * time.Second)
                    }
                }
            }
        }(in)
    
        // Listening for output events
        go func(out chan struct{}) {
    
            for _ = range out {
                fmt.Println("Got an event!")
            }
        }(out)
    
        // Do not let main terminate.
        done := make(chan struct{})
        <-done
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog