bill
bill

Reputation: 728

Multithread Python exit

I have an API and I want to create a client to send/recv data from the interne, so I used a thread so my api won't freeze because of the blocking commands. In my thread I loop while I write/read data. Problem is that after 1 loop program exits and I don't know why.

here is my thread class

class WorkerThread(Thread):
"""Worker Thread Class."""
def __init__(self):
    """Init Worker Thread Class."""
    Thread.__init__(self)
    self._want_abort = 0
    # This starts the thread running on creation, but you could
    # also make the GUI thread responsible for calling this
    self.start()

def run(self):
    while(1):
        if self._want_abort:
           # Use a result of None to acknowledge the abort (of
            # course you can use whatever you'd like or even
            # a separate event type)
            wx.PostEvent(ResultEvent(None))
            return
        Socket_ID=OPEN_CLIENT(str('184.106.153.149'), 3000, 80, SOCKET_STREAM)

        WRITE(Socket_ID, 123, len(123))
        time.sleep(0.5)
        test = READ(Socket_ID)
        if 'on' in test:
            SET_IO(1,1)
        if 'off' in test:
            SET_IO(1,0)

        time.sleep(1)
        CLOSE(Socket_ID)
        time.sleep(10)


def abort(self):
    """abort worker thread."""
    # Method for use by main thread to signal an abort
    self._want_abort = 1

And I call it inside my main after i trigger a checkbox event:

def receive_data(self, event):
        if self.get_cmd == 0:

            self.get_cmd = 1
            self.worker = WorkerThread(self)

        else:
            self.get_cmd = 0
            self.worker.abort()

I saw the Thread class from here: http://wiki.wxpython.org/LongRunningTasks

If I use this, the I/O between client server is OK but API is getting frozed

def receive_data(self, event):
        if self.get_cmd == 0:

            self.get_cmd = 1
            self.worker = WorkerThread(self)
            self.worker.join()

        else:
            self.get_cmd = 0
            self.worker.abort()

Ok, here is another approch that loops 3-4 times and then it crushes:

def receive_data(self, event):

        if self.get_cmd == 0:
            self.thingspeak = threading.Thread(target=recv_data_thingspeak, args = (self.talkback_field.GetValue(),))
            self.thingspeak.start()

        else:
            self.receive_bt.SetValue(True)



def recv_data_thingspeak(queue):

    Socket_ID =OPEN_CLIENT(str('184.106.153.149'), 3000, 80, SOCKET_TYPE_STREAM)
    while(1):

        request = "GET /apps/thinghttp/send_request?api_key=" + queue + " HTTP/1.1\r\n"
        request += "Host: api.thingspeak.com\r\n\r\n"

        WRITE(Socket_ID, 123, len(123))
        time.sleep(1)
        test = READ(Socket_ID)
        if 'on' in test:
            SET_IO(1,1)
        if 'off' in test:
            SET_IO(1,0)

        time.sleep(10)

    CLOSE(Socket_ID)

Upvotes: 1

Views: 172

Answers (1)

johntellsall
johntellsall

Reputation: 15180

Multiple threads can be confusing. For example, in the first batch of code the parent htread is setting (workerthread)._want_abort. However this flag only exists in the parent, not in the worker, so this type of signalling doesn't work.

Generally multithreaded programs work by creating a Queue (or Event, etc) in the parent, then creating a bunch of workers -- giving each one a reference to the Queue. Then when the parent or worker uses the Queue, all threads see the result. You can't do this with a list or other "primitive" object; the Queue has magic so that multiple threads can modify it, and the others will be informed

In the following we start three workers, wait a second, then signal them all to die. We do this by creating an Event in the parent, and sharing it with each worker.

import time
from threading import *

class WorkerThread(Thread):
    def __init__(self, die_flag, *args, **kw):
        super(WorkerThread,self).__init__(*args, **kw)
        self.die_flag = die_flag

    def run(self):
        for num in range(3):
            if self.die_flag.is_set():
                print "{}: bye".format(
                    current_thread().name
                    )
                return
            print "{}: num={}".format(
                current_thread().name, num,
                )
            time.sleep(1)

flag = Event()

print 'STARTING THREADS'
WorkerThread(name='whiskey', die_flag=flag).start()
WorkerThread(name='syrup', die_flag=flag).start()
WorkerThread(name='bitters', die_flag=flag).start()

print '\nRELAXING'
time.sleep(2)

print '\nTELL WORKERS TO DIE'
flag.set()

print '\nWAITING FOR WORKERS'
for thread in enumerate():
    if thread != current_thread():
        print thread.name,':',
        thread.join()
        print 'joined'

print '\nDONE'

Sample run:

STARTING THREADS
whiskey: num=0
syrup: num=0
bitters: num=0

RELAXING
syrup: num=1
whiskey: num=1
bitters: num=1
syrup: num=2
bitters: num=2

TELL WORKERS TO DIE
 whiskey: num=2

WAITING FOR WORKERS
whiskey : joined
bitters : joined
syrup : joined

DONE

Upvotes: 1

Related Questions