我一直在一个Python应用程序中遇到问题。该应用程序具有一个GUI,该GUI接受来自websocket客户端的数据。另外,GUI为每个客户端执行一个附加线程,称为 worker线程,该线程定期查询并将命令发送给客户端。 工作线程使用threading.Timer
个对象。 GUI和客户端运行24/7。
在我当前的设置中,我只有两个客户端。 工作线程每5秒执行一次。问题是,工作线程每3天“无法启动新线程”。解决此问题的唯一方法是重新启动python应用程序。发生此异常时,我期望的运行线程数为:5(使用threading.active_count()
)。这与应用程序愉快运行时正在运行的线程数相同。
不幸的是,我无法为我的问题创建一个最小的工作示例。以下是我的带有两个threading.Timer
对象的应用程序的最小示例。
import threading
import asyncio
from tkinter import *
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import socket
counter_1 = 0
counter_2 = 0
dt = 0.00000001
def increment_counter_1():
global counter_1
global t1
# Do some work:
counter_1 += 1
if counter_1 % 10 == 0:
print("Counter 1: %d" % counter_1)
# Unclear what this does, but it is required in the real application:
asyncio.set_event_loop(asyncio.new_event_loop())
# Delete the timer:
del t1
# Setup the timer again:
t1 = threading.Timer(dt, increment_counter_1)
# Start the timer again:
t1.start()
def increment_counter_2():
global counter_2
global t2
# Do some work:
counter_2 += 1
if counter_2 % 10 == 0:
print("Counter 2: %d" % counter_2)
# Unclear what this does, but it is required in the real application:
asyncio.set_event_loop(asyncio.new_event_loop())
# Delete the timer:
del t2
# Setup the timer again:
t2 = threading.Timer(dt, increment_counter_2)
# Start the timer again:
t2.start()
t1 = threading.Timer(dt, increment_counter_1)
t2 = threading.Timer(dt, increment_counter_2)
# Dummy GUI to emulate the real application:
class TestGui(object):
def __init__(self):
self.root = Tk()
# * Start Button: *
self.startBut = Button(self.root, text="Start Button")
self.startBut.pack()
self.startBut.bind("<Button-1>", self.startButCallback)
def startButCallback(self, event):
# Start the thread:
global t1
global t2
global TT
t1.start()
t2.start()
# Start the tornado server, although it will do nothing in this example:
TT.start_server()
def start(self):
self.root.mainloop()
class DummyHandler:
def __init__(self):
print("Hello")
class TornadoThread (threading.Thread):
def __init__(self):
self.t = threading.Thread(target=self.run, args=())
self.application = tornado.web.Application([(r'/ws', DummyHandler)])
self.http_server = tornado.httpserver.HTTPServer(self.application)
self.http_server.listen(4444)
self.io_loop = tornado.ioloop.IOLoop.current()
def run(self):
myIP = socket.gethostbyname(socket.gethostname())
# Create an event loop:
asyncio.set_event_loop(asyncio.new_event_loop())
# Create an IOLoop:
self.io_loop.start()
def start_server(self):
print("Tornado server started.")
self.t.start()
TG = TestGui()
TT = TornadoThread()
if __name__ == "__main__":
# Start the GUI:
TG.start()
在GUI中按下按钮以启动线程。我已经在计算机上运行了几天的示例应用程序,而没有出现“无法启动新线程”的问题。
我想知道是否有人知道解决我的问题,或者改进我的代码?我在论坛上搜寻了解决方案,但是大多数解决方案都涉及某种类型的线程池。这不是我的问题,线程数永远不会超过5。
有人知道您可以启动和停止的最大线程数吗?
我当前正在最新的软件包和操作系统上运行:Windows 10,Python 3.7,龙卷风5.1.1。
谢谢!
达米恩