вопрос об идеальной структуре потока (связан с многопоточным взаимодействием) - PullRequest
2 голосов
/ 01 ноября 2010

Я пишу приложение, которое прослушивает звуковые события (используя сообщения, передаваемые с помощью Open Sound Control), а затем на основе этих событий приостанавливает или возобновляет выполнение программы.Моя структура работает большую часть времени, но в главном цикле всегда взрывается, поэтому я предполагаю, что это проблема с потоками.Вот общая упрощенная версия того, о чем я говорю:

import time, threading

class Loop():
    aborted = False

    def __init__(self):
        message = threading.Thread(target=self.message, args=((0),))
        message.start()

        loop = threading.Thread(target=self.loop)
        loop.start()


    def message(self,val):

        if val > 1:
            if not self.aborted:
                self.aborted = True
                # do some socket communication            
            else:
                self.aborted = False
                # do some socket communication


    def loop(self):
        cnt = 0

        while True:
            print cnt
            if self.aborted:
                while self.aborted:
                    print "waiting"
                    time.sleep(.1);
            cnt += 1


class FakeListener():
    def __init__(self,loop):
        self.loop = loop
        listener = threading.Thread(target=self.listener)
        listener.start()

    def listener(self):
        while True:
            loop.message(2)
            time.sleep(1)



if __name__ == '__main__':

    loop = Loop()

    #fake listener standing in for the real OSC event listener
    listener = FakeListener(loop)

Конечно, этот простой код, кажется, прекрасно работает, поэтому он явно не полностью иллюстрирует мой настоящий код, но вы понимаете, о чем идет речь.Что здесь не включено, так это тот факт, что в каждом цикле пауза и возобновление (путем установки aborted = True / False) приводят к некоторому обмену сокетами, который также включает потоки.основной цикл не всегда срабатывает там, где остановился после звукового события.Это будет работать для ряда событий, но в конечном итоге он просто не отвечает.

Есть какие-нибудь предложения о том, как структурировать этот вид общения между потоками?

ОБНОВЛЕНИЕ:

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

Я не совсем уверен, что здесь делает функция q.task_done ().

import time, threading
import Queue

q = Queue.Queue(maxsize = 0)

class Loop():
    aborted = False

    def __init__(self):
        checker = threading.Thread(target=self.checker)
        checker.setDaemon(True)
        checker.start()

        loop = threading.Thread(target=self.loop)
        loop.start()


    def checker(self):
        while True:
            if q.get() == 2:
                q.task_done()
                if not self.aborted:
                    self.aborted = True
                else:
                    self.aborted = False


    def loop(self):
        cnt = 0

        while cnt < 40:
            if self.aborted:
                while self.aborted:
                    print "waiting"
                    time.sleep(.1)
            print cnt
            cnt += 1
            time.sleep(.1)


class fakeListener():

    def __init__(self):
        listener = threading.Thread(target=self.listener)
        listener.setDaemon(True)
        listener.start()

    def listener(self):
        while True:
            q.put(2)
            time.sleep(1)



if __name__ == '__main__':

    #fake listener standing in for the real OSC event listener
    listener = fakeListener()

    loop = Loop()

1 Ответ

4 голосов
/ 02 ноября 2010

Хмм .. Я не совсем понимаю ваш вопрос, но я сделаю все возможное, чтобы объяснить, что, по моему мнению, вам нужно исправить ваши проблемы.

1) Поток вашей функции Loop.loop должен быть установлен как поток демона, чтобы он завершался с вашим основным потоком (чтобы вам не приходилось завершать процесс python каждый раз, когда вы хотите завершить свою программу) , Для этого просто поместите loop.setDaemon (True) перед вызовом функции «start» потока.

2) Самый простой и надежный способ связи между потоками - это очередь. Поток помещает элемент в эту очередь, а другой поток извлекает элемент, что-то делает с элементом и затем завершает (или получает другую работу)

В python Queue может быть чем угодно, от глобального списка до встроенного в Python объекта Queue. Я рекомендую Python Queue, потому что он потокобезопасен и прост в использовании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...