简体   繁体   中英

How to pause and resume a thread using the threading module?

I have a long process that I've scheduled to run in a thread, because otherwise it will freeze the UI in my wxpython application.

I'm using:

threading.Thread(target=myLongProcess).start()

to start the thread and it works, but I don't know how to pause and resume the thread. I looked in the Python docs for the above methods, but wasn't able to find them.

Could anyone suggest how I could do this?

I was having the same issue myself, until I found the answer.

I did some speed tests as well, the time to set the flag and for action to be taken is pleasantly fast 0.00002 secs on a slow 2 processor Linux box.

Example thread pause test using set() & clear() events

By Rich O'Regan

import threading
import time

# This function gets called by our thread.. so it basically becomes the thread innit..                    
def wait_for_event(e):
    while True:
        print '\tTHREAD: This is the thread speaking, we are Waiting for event to start..'
        event_is_set = e.wait()
        print '\tTHREAD:  WHOOOOOO HOOOO WE GOT A SIGNAL  : %s', event_is_set
        e.clear()

# Main code.. 
e = threading.Event()
t = threading.Thread(name='your_mum', 
                     target=wait_for_event,
                     args=(e,))
t.start()

while True:
    print 'MAIN LOOP: still in the main loop..'
    time.sleep(4)
    print 'MAIN LOOP: I just set the flag..'
    e.set()
    print 'MAIN LOOP: now Im gonna do some processing n shi-t'
    time.sleep(4)
    print 'MAIN LOOP:  .. some more procesing im doing   yeahhhh'
    time.sleep(4)
    print 'MAIN LOOP: ok ready, soon we will repeat the loop..'
    time.sleep(2)

There is no method for other threads to forcibly pause a thread (any more than there is for other threads to kill that thread) -- the target thread must cooperate by occasionally checking appropriate "flags" (a threading.Condition might be appropriate for the pause/unpause case).

If you're on a unix-y platform (anything but windows, basically), you could use multiprocessing instead of threading -- that is much more powerful, and lets you send signals to the "other process"; SIGSTOP should unconditionally pause a process and SIGCONT continues it (if your process needs to do something right before it pauses, consider also the SIGTSTP signal, which the other process can catch to perform such pre-suspension duties. (There may be ways to obtain the same effect on Windows, but I'm not knowledgeable about them, if any).

You can use signals: http://docs.python.org/library/signal.html#signal.pause

To avoid using signals you could use a token passing system. If you want to pause it from the main UI thread you could probably just use a Queue.Queue object to communicate with it.

Just pop a message telling the thread the sleep for a certain amount of time onto the queue.

Alternatively you could simply continuously push tokens onto the queue from the main UI thread. The worker should just check the queue every N seconds (0.2 or something like that). When there are no tokens to dequeue the worker thread will block. When you want it to start again just start pushing tokens on to the queue from the main thread again.

The multiprocessing module works fine on Windows. See the documentation here (end of first paragraph):

http://docs.python.org/library/multiprocessing.html

On the wxPython IRC channel, we had a couple fellows trying multiprocessing out and they said it worked. Unfortunately, I have yet to see anyone who has written up a good example of multiprocessing and wxPython.

If you (or anyone else on here) come up with something, please add it to the wxPython wiki page on threading here: http://wiki.wxpython.org/LongRunningTasks

You might want to check that page out regardless as it has several interesting examples using threads and queues.

You might take a look at the Windows API for thread suspension .

As far as I'm aware there is no POSIX/pthread equivalent. Furthermore, I cannot ascertain if thread handles/IDs are made available from Python . There are also potential issues with Python, as its scheduling is done using the native scheduler, it's unlikely that it is expecting threads to suspend, particularly if threads suspended while holding the GIL, amongst other possibilities.

I had the same issue. It is more effective to use time.sleep(1800) in the thread loop to pause the thread execution.

eg

MON, TUE, WED, THU, FRI, SAT, SUN = range(7) #Enumerate days of the week
Thread 1 : 
def run(self):
        while not self.exit:
            try:
                localtime = time.localtime(time.time())
                #Evaluate stock
                if localtime.tm_hour > 16 or localtime.tm_wday > FRI:
                    # do something
                    pass
                else:
                    print('Waiting to evaluate stocks...')
                    time.sleep(1800)
            except:
                print(traceback.format_exc())

Thread 2
def run(self):
    while not self.exit:
        try:
            localtime = time.localtime(time.time())
            if localtime.tm_hour >= 9 and localtime.tm_hour <= 16:
                # do something
                pass
            else:
                print('Waiting to update stocks indicators...')
                time.sleep(1800)
        except:
            print(traceback.format_exc())

This is Rich's answer for Python 3.x:

import threading
import time

# This function gets called by our thread.. so it basically becomes the thread innit..                    
def wait_for_event(e):
    while True:
        print ('\tTHREAD: This is the thread speaking, we are Waiting for event to start..')
        event_is_set = e.wait()
        print (f'\tTHREAD:  WHOOOOOO HOOOO WE GOT A SIGNAL  : {event_is_set}, event_is_set')
        e.clear()

# Main code.. 
e = threading.Event()
t = threading.Thread(name='your_mum', 
                     target=wait_for_event,
                     args=(e,))
t.start()

while True:
    print ('MAIN LOOP: still in the main loop..')
    time.sleep(4)
    print ('MAIN LOOP: I just set the flag..')
    e.set()
    print ('MAIN LOOP: now Im gonna do some processing n shi-t')
    time.sleep(4)
    print ('MAIN LOOP:  .. some more procesing im doing   yeahhhh')
    time.sleep(4)
    print ('MAIN LOOP: ok ready, soon we will repeat the loop..')
    time.sleep(2)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM