Какой лучший способ создать поток, который можно завершить из основного потока в python?

Я собираю данные с акселерометра. Я хочу, чтобы пользователь мог начать запись данных и остановить запись, нажав кнопку запуска и остановки соответственно. Я решил сделать это с потоками, поэтому кнопка запуска создает поток, который собирает данные, а кнопка остановки останавливает этот поток и захватывает записанные данные.

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

Что я делаю прямо сейчас, так это то, что поток запускает цикл, который записывает данные и проверяет, установлено ли для переменной значение True, если это так, цикл должен закончиться. У меня также есть функция end(), которая предназначена для вызова из основного потока и, как предполагается, устанавливает переменную в значение True, чтобы завершить поток.

class Capture(Thread):
def __init__(self,accel):
    Thread.__init__(self)
    self.accel=accel
    self.ended=False
    self.data=[]
    self.lock=Lock()

def run(self):
    while self.isEnded()==False:
        self.lock.acquire()
        self.data.append(self.accel.read())
        self.lock.release()

def getData(self):
    self.lock.acquire()
    d=self.data
    self.data=[]
    self.lock.release()
    return d

def isEnded(self):
    self.lock.acquire()
    end=self.ended
    self.lock.release()
    return end

def end(self):
    self.lock.acquire()
    self.ended=True
    self.lock.release()

person user467526    schedule 03.04.2013    source источник
comment
может self.accel.read() заблокировать на несколько минут? Пробовали ли вы: data = self.accel.read() \n with lock: self.data.append(data) избежать блокировки getData() надолго. Или читать меньшими порциями до разделителя записей? Или просто используйте Queue.get_nowait() без явной блокировки. Вам не нужен замок вокруг self.ended. Если вам нужно дождаться isEnded() в другом потоке; вы могли бы использовать threading.Event.wait(). Вам может вообще не понадобиться поток для чтения из файла без блокировки графического интерфейса, например, GObject.io_add_watch   -  person jfs    schedule 04.04.2013
comment
self.accel.read() не может блокироваться в течение нескольких минут, время ожидания установлено на одну секунду. Проблема не в том, что getData() заблокирован, а в том, что когда я вызываю end(), поток либо немедленно завершается, но не производит данных, либо продолжает работать с нормальной скоростью еще от 5 секунд до нескольких минут. Блок появляется в основном потоке, когда я вызываю thread.end().   -  person user467526    schedule 04.04.2013
comment
Вы пробовали менять?   -  person jfs    schedule 04.04.2013


Ответы (1)


Боюсь, я совсем не очень хорошо знаю python, но предположу. Если accel.read() обращается к какому-то внешнему коду (например, драйверу устройства) и блокируется на секунду, интерпретатор Python также блокируется. Ни один другой поток не будет запущен. Когда чтение, наконец, возвращается, вы снимаете блокировку. В этот момент интерпретатор должен будет решить, что делать дальше, и ваш поток просто зацикливается, снова берет блокировку и возвращается к чтению (и блокируется)

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

Может ли это быть?

person bazza    schedule 04.04.2013