0

Ich habe einen Producer-Thread, der Daten von einer seriellen Verbindung erzeugt und sie in mehrere Warteschlangen einfügt, die von verschiedenen Consumer-Threads verwendet werden. Ich möchte jedoch zusätzliche Warteschlangen (zusätzliche Konsumenten) aus dem Hauptthread hinzufügen können, nachdem der Produzententhread bereits gestartet wurde.Wie kann man in einem laufenden Thread in Python eine Methode ändern oder aufrufen?

I.e. Wie kann ich im folgenden Code eine Warteschlange zu listOfQueues aus dem Hauptthread hinzufügen, während dieser Thread ausgeführt wird? Kann ich eine Methode wie addQueue (newQueue) zu dieser Klasse hinzufügen, die daran anfügt listOfQueues? Dies scheint nicht wahrscheinlich, da der Thread in der Run-Methode sein wird. Kann ich eine Art Ereignis ähnlich dem Stop-Ereignis erstellen?

class ProducerThread(threading.Thread): 
    def __init__(self, listOfQueues): 
     super(ProducerThread, self).__init__() 
     self.listOfQueues = listOfQueues 
     self._stop_event = threading.Event() # Flag to be set when the thread should stop 

    def run(self): 
     ser = serial.Serial() # Some serial connection 

     while(not self.stopped()): 
      try: 
       bytestring = ser.readline() # Serial connection or "producer" at some rate 
       for q in self.listOfQueues: 
        q.put(bytestring) 
      except serial.SerialException: 
       continue 

    def stop(self): 
     ''' 
     Call this function to stop the thread. Must also use .join() in the main 
     thread to fully ensure the thread has completed. 
     :return: 
     ''' 
     self._stop_event.set() 

    def stopped(self): 
     ''' 
     Call this function to determine if the thread has stopped. 
     :return: boolean True or False 
     ''' 
     return self._stop_event.is_set() 
+0

Sie haben das 'self. in' q in listOfQueues: 'verpasst. – 101

Antwort

0

Sicher, Sie können einfach eine Append-Funktion haben, die zu Ihrer Liste hinzufügt. Z.B.

def append(self, element): 
    self.listOfQueues.append(element) 

, die funktioniert auch nach dem Thread start() Methode aufgerufen wurde.

Edit: für nicht Thread-sichere Verfahren können Sie eine Sperre verwenden, zB:

def unsafe(self, element): 
    with self.lock: 
     # do stuff 

Sie würden dann müssen auch die Sperre in Ihrer run Methode hinzufügen, zum Beispiel:

with lock: 
    for q in self.listOfQueues: 
     q.put(bytestring) 

Jeder Code, der eine Sperre erwirbt, wartet auf die Freigabe der Sperre an anderer Stelle.

+0

danke. Da es die GIL gibt und der Thread standardmäßig alle 100 Anweisungen wechselt, gibt es einen Fall, in dem dieser Thread mitten in der for-Schleife stoppt und im Hauptthread eine Warteschlange zu self.listOfQueues hinzugefügt wird und es ein Problem verursacht, weil Produzent Thread ist in der Mitte der Schleife? –

+0

Nein, da "append" Thread-sicher ist: https://Stackoverflow.com/a/18568017/1470749. Wenn Sie komplexere Prozeduren ausführen möchten, die nicht Thread-sicher sind, können Sie dies mithilfe einer Sperre tun (siehe Bearbeiten). – 101

+0

@ThomasJacobs Dann fügen Sie die neue 'Queue' in eine separate Liste' new_queues' hinzu. Hängen Sie 'new_queues' an' listOfQueues' nach der 'for'-Schleife in der' run' Methode an. –

Verwandte Themen