无法使用threading.Timer

时间:2018-11-29 13:03:05

标签: python multithreading

我一直在一个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。

谢谢!

达米恩

0 个答案:

没有答案