当我尝试终止运行在单独线程上运行的长时间运行进程时,我遇到了问题。
以下是该计划。 WorkOne创建一个子进程并运行一个生成日志行的长时间运行的进程“adb logcat”。我在main()中启动WorkOne,等待5秒并尝试停止它。多次运行提供多个输出
import threading
import time
import subprocess
import sys
class WorkOne(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.process = subprocess.Popen(['adb','logcat'], stdout=subprocess.PIPE, stderr=sys.stdout.fileno())
def run(self):
for line in iter(self.process.stdout.readline,''):
#print line
if self.event.is_set():
self.process.terminate()
self.process.kill()
break;
print 'exited For'
def stop(self):
self.event.set()
def main():
print 'starting worker1'
worker1 = WorkOne()
worker1.start()
print 'number of threads: ' + str(threading.active_count())
time.sleep(5)
worker1.stop()
worker1.join(5)
print 'number of threads: ' + str(threading.active_count())
if __name__ == '__main__':
main()
有时我得到[A]:
starting worker1
number of threads: 2
number of threads: 2
exited For
有时我得到[B]:
starting worker1
number of threads: 2
number of threads: 1
exited For
有时我得到[C]:
starting worker1
number of threads: 2
number of threads: 2
我想我应该一直得到[B]。这里出了什么问题?
答案 0 :(得分:0)
更改
if self.event.is_set():
self.process.terminate()
self.process.kill()
break;
到
if self.event.is_set():
self.process.terminate()
self.process.wait()
break
分号是一个死的赠品,这里有一个问题。
我猜测,如果没有wait()
,线程有时会很快解锁work1.join(5)
。在这些情况下,threading.active_count()
会返回2.
而且,正如@ A.Rodas所说,work1.join(5)
应为work1.join()
,以确保在work1
完成之前联接不会取消阻止。
顺便说一下,我不确定你为什么要连续拨打terminate
然后kill
。在Unix上,kill是一种更严格的终止形式。在Windows上,它们是相同的。因此,如果您打算调用kill,则无需调用terminate。
由于你知道subprocess
调用的程序,你也应该知道终止是否足以阻止它。
因此,您只需要一个:self.process.terminate()
或self.process.kill()
。
答案 1 :(得分:0)
我认为[B]只有在子进程少于10秒时才有可能:主线程休眠5秒,之后worker
在join()
的5秒超时内完成。
对于10秒或更长时间,worker
即使在join()
调用之后也可以存活,因为它有超时参数,这可能发生与否。然后你可以得到[A](子流程几秒钟后完成)或[C](子流程很快完成)。
要获得[B],请删除join()
的超时参数,以便主线程等待worker
完成(或确保在10秒内通过将kill调用置于循环)。