J.Doe
J.Doe

Reputation: 97

How to terminate a thread in python after a certain amount of time?

I have multiple threads that run a while loop. I would like to terminate these threads after a given amount of time. I am aware of other questions similar to this but I don't see how I can transfer those answers to my code.

 def function1(arg1, arg2, arg3, duration):
        t_end = time.time() + duration
        while time.time() < t_end:
            #do some stuff

for i in range(100):
    t = Thread(target = function1, args=(arg1, arg2, arg3, 10))
    t.start()

This opens 100 threads but they never close. How can I close these threads after the specified time, in this example 10 seconds? My function opens a socket.

Upvotes: 1

Views: 2762

Answers (2)

NuclearPeon
NuclearPeon

Reputation: 6049

Use a mixture of terminating a thread (info found here: Is there any way to kill a Thread in Python?)

and threading timer objects: https://docs.python.org/2/library/threading.html#timer-objects

The code below works for me, but the fact it keeps throwing a TypeError has got me puzzled. I can't seem to find much information on why it's happening or how to prevent it:

threadingtest.py

#!/usr/bin/env python3
import time
import threading

class StoppableThread(threading.Thread):
    """Thread class with a stop() method. The thread itself has to check
    regularly for the stopped() condition."""

    def __init__(self):
        super(StoppableThread, self).__init__()
        self._stop = threading.Event()

    def stop(self):
        self._stop.set()
        try:
            self.join()

        except TypeError as tE:
            print("Shutting down")

    def stopped(self):
        return self._stop.isSet()

class MyStoppableThread(StoppableThread):

    def __init__(self, *args):
        super(MyStoppableThread, self).__init__()
        self.args = args # Use these in the thread

    def run(self):
        print("Started my thread with arguments {}".format(self.args))
        while not self.stopped():
            time.sleep(1)
            # THIS IS WHERE YOU DO THINGS

if __name__ == "__main__":
    threads = []
    for i in range(100):
        t = MyStoppableThread(i, 'a', 'b', 'c')
        t.start()
        threads.append(t)

    print("\n:: all threads created\n")
    time.sleep(5)
    print("\n:: killing all threads\n");
    for t in threads:
        t.stop()

Upvotes: 1

jmunsch
jmunsch

Reputation: 24089

You could pass a callback to each thread. And create a thread list.

threadlist  = {}
def cb(id, currtime):
    t = threadlist[id]
    d = currtime - t.starttime
    if d > 10:
        return True
    else:
        return False

def function1(arg1, arg2, arg3, duration, cb, threadid):
    t_end = time.time() + duration
    while time.time() < t_end:
        #do some stuff
        if cb(threadid, time.time()):
            break

for i in range(100):
    t = Thread(target = function1, args=(arg1, arg2, arg3, 10, cb, i))
    threadlist[id] = {"starttime": time.time(), "thread": t}
    t.start()

And to check:

time.sleep(15)
for item in threadlist.values():
    print(item.thread.is_alive())

Upvotes: 1

Related Questions