线程即将终止怎么办? [英] What to do with thread being about to terminate?

查看:69
本文介绍了线程即将终止怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个即将终止的正在运行的线程,但是到那时,我已经想摆脱它的引用了.我可以将它拉开序幕并希望达到最佳状态吗?还是应该以某种特殊的方式来处理它?<​​/p>

I'm having a running thread that is about to terminate, but at that point, I already want to get rid of its reference. Can I just kick it off and hope for the best or should I handle it in some special way?

class CoolThing(object):

    def __init__(self):
        self.thread = None

    def run_in_background(self, callback, period=0.5):
        if self.thread:
            raise RuntimeError

        def worker():
            worker.running = True
            while worker.running:
                if some_event():
                    callback(self)
                time.sleep(period)

        self.thread = (threading.Thread(target=worker), worker)
        self.thread[0].start()

    def stop_background(self, join=False):
        if not self.thread:
            raise RuntimeError

        # Make the worker function end harmfully.
        self.thread[1].running = False

        if join:
            self.thread[0].join()

        # What should I now do with the thread being about to
        # terminate, when not being joined?

        # ...

        self.thread = None

推荐答案

在while循环离开时,您应该在从worker内部引发的回调中将线程设置为无".

You should set thread to None in a callback that is evoked from within worker, when the while-loop is left:

编辑:现在还支持立即重启后台进程

Edit: Now also support immediate restart of background process

import time
import threading

class CoolThing(object):

    def __init__(self):
        self.thread = None

    def run_in_background(self, callback, period=0.5):
        wait_count = 0
        while True:
            if self.thread:
                if self.thread[1].running or wait_count>10:
                    raise RuntimeError()
                time.sleep(0.5)
                wait_count += 1
            else:
                break

        def worker():
            t0 = time.time()
            worker.running = True
            while worker.running:
                if time.time()-t0>2:
                    callback()
                    t0 = time.time()
                time.sleep(period)
            worker.callback()

        worker.callback = self.dispose
        self.thread = (threading.Thread(target=worker), worker)
        self.thread[0].start()

    def stop_background(self, join=False):
        if not self.thread:
            raise RuntimeError
        self.thread[1].running = False
        if join:
            self.thread[0].join()
        self.stopping = True

    def dispose(self):
        self.thread = None
        self.stopping

def my_callback():
    print "Beep"

if __name__=="__main__":
    cool_thing = CoolThing()
    cool_thing.run_in_background(my_callback, 0.5)
    time.sleep(10)
    cool_thing.stop_background()
    # Immediatley restart process
    cool_thing.run_in_background(my_callback, 0.5)
    time.sleep(10)
    cool_thing.stop_background()
    print cool_thing.thread
    time.sleep(3)
    print cool_thing.thread

给出输出:

Beep
Beep
Beep
(<Thread(Thread-2, started 10760)>, <function worker at 0x02DEDD70>)
None

因此,在调用stop_background之后,self.thread仍然会被设置,但是稍后它是None.您还可以保存其名称worker.callback-variable并调用dispose(),但是这样,代码更加灵活.

So immediately after calling stop_background, self.thread is still set, but later, it's None. You could also save on the worker.callback-variable and call dispose() by it's name, but this way, the code is more flexible.

编辑2 :新要求,新代码示例

Edit 2: New requirements, new code sample

我为工人(SRP)设置了一个单独的类,CoolThing拥有此类工人的列表.如果启动了run_background(...),它将检查是否有任何工作进程仍在运行(不请求停止),然后引发RuntimeError.否则,开始新的工作人员. stop_background()告诉每个工作程序停止,每个工作程序调用一个回调,然后将该回调程序从所有工作程序的列表中删除.

I made a separate class for worker (SRP) and CoolThing hold a list of such workers. If run_background(...) is started, it checks if any of the workers is still running (no stop requested), then raises RuntimeError. Otherwise, starts a new worker. stop_background() tells each worker to stop, and each worker invokes a callback, which then removes this worker from the list of all workers.

import time
import threading

class Worker(threading.Thread):
    def __init__(self, callback, period=0.5, finished_callback = None):
        threading.Thread.__init__(self)
        self.callback = callback
        self.period = period
        self._stop_requested = False
        self._finished_callback = finished_callback

    def run(self):
        t0 = time.time()
        while not self._stop_requested:
            if time.time()-t0>2:
                self.callback()
                t0 = time.time()
            time.sleep(self.period)
        if self._finished_callback:
            self._finished_callback(self)

    def request_stop(self):
        self._stop_requested = True

    @property
    def stopping(self):
        return self._stop_requested

class CoolThing(object):

    def __init__(self):
        self.workers = []
        self.workers_lock = threading.Lock()

    def run_in_background(self, callback, period=0.5):
        if len([w for w in self.workers if not w.stopping])>0:
            raise RuntimeError()
        worker = Worker(callback, period, finished_callback=self.dispose)
        with self.workers_lock:
            self.workers.append(worker)
        worker.start()

    def stop_background(self, join=False):
        if len(self.workers) == 0:
            raise RuntimeError()
        for worker in self.workers:
            worker.request_stop()
        if join:
            for worker in self.workers:
                worker.join()

    def dispose(self, worker):
        with self.workers_lock:
            self.workers.remove(worker)

def my_callback():
    print "Beep"

if __name__=="__main__":
    cool_thing = CoolThing()
    cool_thing.run_in_background(my_callback, 0.5)
    time.sleep(10) 
    print cool_thing.workers
    cool_thing.stop_background()
    # Immediatley restart process
    cool_thing.run_in_background(my_callback, 0.5)    
    print cool_thing.workers
    time.sleep(5)
    print cool_thing.workers
    time.sleep(5)
    cool_thing.stop_background()
    print cool_thing.workers
    time.sleep(3)
    print cool_thing.workers

这篇关于线程即将终止怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆