Два потока, один объект
Я пишу драйвер Linux для устройства USB HID на Python. Устройство имеет два способа отправки данных, оба из которых необходимы: отчеты о функциях (синхронно) и отчеты о входах (асинхронно). Использование библиотеки Cython hidapi У меня есть только один экземпляр устройства для работы, но мне нужно настроить прослушиватель для hid.read(), который будет работать постоянно И разрешать приложению вызывать синхронные методы по желанию для отправки функции отчеты.
В настоящее время у меня есть слушатель в одном потоке и синхронные вызовы в другом. Когда я запускаю программу, мои синхронные вызовы не происходят, хотя они работают нормально, если я никогда не запускаю слушателя; таким образом, кажется, что поток слушателя вступает во владение.
Ниже приведен тревожный фрагмент кода:
app.py
# app.py
import threading
import time
import myhiddriver
# Code that sets mydevice
class Reader:
def start(self, device):
self.requests = myhiddriver.DeviceRequest(device)
# Wait a bit before firing, for testing
time.sleep(3)
self.requests.request_swipe_card()
def start_listener(self, device):
self.listener = myhiddriver.DeviceListener(device)
reader = Reader()
thread1 = threading.Thread(target=reader.start, args=(mydevice,))
thread1.daemon = True
thread2 = threading.Thread(target=reader.start_listener, args=(mydevice,))
thread2.daemon = True
thread1.start()
thread2.start()
# Keep this puppy running
while True:
pass
myhiddriver.py
import threading
LOCK = threading.Lock()
class DeviceRequest:
def __init__(self, device):
# Lock it up first
LOCK.acquire()
self.device = device
LOCK.release()
def request_swipe_card(self):
# Lock this up too
LOCK.acquire()
self.device.set_feature_report(insert data here)
LOCK.release()
class DeviceListener:
def __init__(self, device):
# Lock me up
LOCK.acquire()
self.device = device
self.start_listener()
LOCK.release()
def start_listener(self):
while True:
# Should I be locking this up?
LOCK.acquire()
data = self.device.read(255)
LOCK.release()
if data:
print data
else:
pass
Мой вопрос: почему мой синхронный вызов (request_swipe_card) не выполняется? Или, как я могу лучше спроектировать это, чтобы иметь бесконечного слушателя И возможность делать синхронные вызовы на одном и том же объекте?
1 ответ
Судя по всему, это потому, что вы его блокируете
Когда состояние разблокировано, acqu () изменяет состояние на заблокированное и немедленно возвращается. Когда состояние заблокировано, acqu () блокируется, пока вызов release() в другом потоке не изменит его на разблокированный
вот проблема:
class DeviceListener:
def __init__(self, device):
LOCK.acquire() # first you lock it up
self.device = device
self.start_listener()
LOCK.release()
def start_listener(self):
while True: # because of the loop, the lock wouldn't get release even if the LOCK below doesn't exist
LOCK.acquire() # it end up blocking here and oops, it locked up xD
data = self.device.read(255) # so it wouldn't be able to read here
LOCK.release()
if data:
print data
else:
pass
и когда request_swipe_card
в конечном итоге вызов в другом потоке, он тоже там блокирует
def request_swipe_card(self):
LOCK.acquire() # right here xD
self.device.set_feature_report(insert data here)
LOCK.release()