<p>你觉得这些线为什么会死?在<code>CopyWorker</code>中没有任何东西可以突破<code>while True</code>循环,因此我希望线程可以无限期地保持活动状态。一旦所有的项目都被消耗了,它们将被永久阻止尝试从空队列中<code>get</code>另一个值,但是它们不会退出或释放它们的资源。在</p>
<p>如果你想让你的线程在没有更多的工作要做时退出,你需要告诉他们这样做。一种常见的方法是通过队列发送一个sentinel值,消费线程会将其识别为不再有数据的信号。您需要为每个启动的线程发送一个sentinel副本。下面是一个基于当前代码的快速未经测试的解决方案。我使用<code>None</code>作为sentinel,因为它看起来不像是文件名的正常值。在</p>
<pre><code>def CopyWorker(self, progressBar):
while True:
fileName = fileQueue.get()
if fileName is None: # check for sentinel value here
fileQueue.task_done()
return
shutil.copy(fileName[0], fileName[1])
fileQueue.task_done()
with self.lock:
self.copyCount += 1
if not progressBar:
print str(self.copyCount) + "of" + str(self.totalFiles)
percent = (self.copyCount * 100) / self.totalFiles
print "File copy: " + str(percent) + "%"
else:
progressBar.setValue(self.copyCount)
def threadWorkerCopy(self, fileNameList, progressBar=False):
threadCount = 10
for i in range(threadCount):
t = threading.Thread(target=self.CopyWorker, args=(progressBar,))
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
for i in range(threadCount): # send sentinel values from here
fileQueue.put(None)
fileQueue.join()
</code></pre>
<p>为了简单起见,我省略了一些你可以做的事情。例如,最好保留对每个启动线程的引用,并从主线程中<code>join</code>它们都已退出。这可能是<code>join</code>排队的替代方案。如果线程正常退出,也没有理由让它们成为守护进程。在</p>
<p>您还可以重新排序一些代码,这样就不需要两个<code>for i in range(threadCount)</code>循环。如果您<code>put</code>首先将所有值放入队列中,那么在启动线程之前,可以将这两个循环组合起来。在</p>