2015-08-04 4 views
1

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

Рассмотрим методы ниже, как это -

def pause_my_operation(): 
    with self._lock: 
     # check if there is already an existing timer, if present then cancel the timer and start a new timer 
     # pause the operation 

def pausetimeout(): 
    with self._lock: 
     # check if there is already an existing timer, if present then cancel it. 
     # resume the operation 

Операция имеет два места в пользовательском интерфейсе, откуда она может быть приостановлена. Следовательно, проверка таймера в методе паузы.

Теперь проблема заключается в том, что между этими двумя функциями может быть гонка. Если первая пауза увольняется некоторое время раньше, и срок ее действия истекает, т. Е. Pausetimeout первой паузы только что ввел метод , но перед тем, как получить блокировку, есть второй вызов из пользовательского интерфейса, чтобы приостановить операцию, т. е. вызывается pause_my_operation и получает блокировку. Вторая pause_my_operation просто установит внутреннее событие, чтобы отметить отмененный таймер, но это может не остановить выполнение pausetimeout, поскольку он уже обслуживается. В результате этого второй вызов паузы не будет иметь никакого эффекта, и таймер будет отменен таймаутом для первой паузы.

Любая идея, как я могу решить эту проблему?

ответ

2

Вы можете создать переменную, которая будет увеличена на pause_my_operation() и уменьшена на pausetimeout(). Тогда pausetimeout() выполнит только свою логику, если после декремента переменная равна 0. С этой логикой только последний pausetimeot() возобновит код.

Например:

def pause_my_operation(): 
    with self._lock: 
     self._counter += 1 
     # check if there is already an existing timer, if present then cancel the timer and start a new timer 
     # pause the operation 

def pausetimeout(): 
    with self._lock: 
     self._counter -= 1 
     if self._counter == 0: 
      # check if there is already an existing timer, if present then cancel it. 
      # resume the operation 

Редактировать

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

def pause_my_operation(): 
    with self._lock: 
     self._counter += 1 
     # start a new timer 
     # pause the operation 

def pausetimeout(): 
    with self._lock: 
     self._counter -= 1 
     if self._counter == 0: 
      # resume the operation 

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

+0

Спасибо! Это работает :) –

+0

Я только что понял, что есть еще одно условие гонки, но все в порядке, я немного изменил проверки ... –

+0

На самом деле, мне нужно отменить старый таймер, потому что мне нужно показать новое значение возобновления в пользовательском интерфейсе. Может ли он работать, если я проверю идентификатор потока в функции pausetimeout, т. Е. Отмените таймер и возобновит операцию, только если совпадение идентификатора. Таким образом, для вызова второй паузы идентификатор потока будет другим, поэтому threading.current_thread(). Ident и self .__ timer.ident будут отличаться. Я исправлю здесь? –

Смежные вопросы