两个线程,一个对象

时间:2014-11-08 20:49:31

标签: python multithreading hid hidapi

我正在为Python中的USB HID设备编写Linux驱动程序。该设备有两种发送数据的方式,这两种方式都是需要的:功能报告(同步)和输入报告(异步)。使用hidapi Cython库我只有一个设备实例可以使用,但我需要为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 个答案:

答案 0 :(得分:3)

从代码的外观来看,这是因为你把它锁起来了

  

当状态解锁时,acquire()将状态更改为锁定状态   马上回来。当状态被锁定时,acquire()会阻塞直到   在另一个线程中调用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()