Как остановить время. Таймер, который в настоящее время слушается в другой рутине? - PullRequest
0 голосов
/ 28 июня 2018

У меня есть время ожидания простоя таймер select включен в программе, если я вижу активность, я хочу отменить таймер.

Я посмотрел на документацию , и я не уверен, что понимаю, что там написано.

func (t *Timer) Stop() bool
Стоп предотвращает срабатывание таймера. Он возвращает истину, если вызов останавливает таймер, ложь, если таймер уже истек или был остановлен. Стоп не закрывает канал, чтобы предотвратить некорректное чтение канала.

Чтобы предотвратить срабатывание таймера, созданного с помощью NewTimer после вызова Stop, проверьте возвращаемое значение и опустошите канал. Например, если программа еще не получила от t.C:

if !t.Stop() { <-t.C }

Это нельзя сделать одновременно с другими приемами от канала таймера.

Я пытаюсь понять, когда мне нужно вручную слить канал.

Я перечислю свое понимание, и если я ошибаюсь, поправьте меня.

Если Stop вернул false, это означает либо:

  • Таймер уже остановлен
    • В этом случае чтение с канала заблокируется, поэтому я не должен этого делать
  • Таймер уже истек
    • Поскольку у меня на канале слушается другая программа, могу ли я знать наверняка, получил ли она событие?
    • Из «это не может быть сделано одновременно с другими получениями» В части документации выясняется, что это не вариант, так что мне делать?

В моем случае получение лишнего события из таймера не имеет большого значения, это говорит о том, что мне следует делать здесь?

1 Ответ

0 голосов
/ 28 июня 2018

Причина, по которой вам, возможно, понадобится истощить канал, заключается в том, как запланированы горутины.

Проблема

Представьте себе этот случай:

  1. Создан таймер
  2. Таймер срабатывает, отправляя значение на t.C
  3. Ничто еще не получило / не прочитало значение, но вызывается t.Stop().

В этом случае на канале есть значение t.C, и t.Stop() возвращает значение false, поскольку «таймер уже истек» (т. Е. Когда он отправил значение на t.C).

Причина, по которой в документах говорится, что «это нельзя сделать одновременно с другими получателями», заключается в том, что нет гарантии порядка между if !t.Stop { и <-t.C. Команда stop может вернуть false, введя тело if. И тогда можно было бы запланировать другую процедуру и прочитать значение из t.C, которое пыталось истощить в теле оператора if. Это приведет к возникновению данных и блокированию внутри оператора if. (как вы указали в своем вопросе!)

Решение

Это зависит от поведения слушающей таймер вещи.

Если вы просто выберите:

select {
    case result <- doWork():
    case <-t.C
}

Нечто подобное выше. Может произойти одно из нескольких:

  1. Работу можно было бы сделать с doWork, отправив результат, все хорошо.
  2. Таймер может срабатывать, вызывая тайм-аут и прерывая выбор.
  3. Вызов, чтобы остановить, остановить таймер, единственный выход из выбора - doWork() завершение.
  4. Таймер может сработать, другие обычные вызовы t.Stop(), но это слишком поздно, потому что значение было отправлено, вызывая тайм-аут, разрыв выбор.

Пока вы в порядке с делом 4, вам не нужно взаимодействовать / истощать канал после вызова Stop.

Если вы не в порядке с делом 4. Вы по-прежнему не можете использовать канал t.C, потому что его слушает другая программа. Это может заблокировать в операторе if. Вместо этого вы должны найти другой способ выложить код или убедиться, что ваша программа в списке выбора все еще не прослушивает канал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...