带有TKINTER的多线程 - 线程永不发布锁
我有一个TKINTER应用程序,该应用程序连接到串行上的专有传感器,并用Python控制它。我试图拥有一个线程,该线程总是在后台运行,以检测连接是否死亡,显示警报并允许用户按下按钮重新建立串行连接(在另一个线程中也进行重新连接)。由于某种原因,com监视器线程正常工作,当我拔下串行电缆时,它会显示一个弹出窗口并启用按预期的重新连接按钮,但是当我重新连接一到两次时,重新连接的线程只是停止释放锁。我已经使用打印语句检查了一下。
这是产生通过串行重新连接的线程的代码。按下重新连接按钮时,将产生此线程。
def spawn_reconnect_to_mote_thread(self):
self.reconnect_thread = threading.Thread(target=self.reconnect_to_mote)
self.reconnect_thread.daemon = True
self.reconnect_thread.name = 'reconnect'
self.reconnect_thread.start()
这是重新连接函数。我们还使用Python编写的专有控制软件,这就是为什么语法看起来很奇怪的原因。该软件具有自己的线程,该线程是在建立连接时产生的。 MOTE_MODEL_MAP只是将正确的控制功能映射到正确的模型ID,该功能可以轻松地将其扩展到不同的硬件模型。
def reconnect_to_mote(self):
with self.lock:
self.connection.close()
self.connection = MOTE_MODEL_MAP[self.mote_model_str ['mote_transport'].Connection({'serial': [self.com_port]})
self.com_model_label['text'] = MOTE_MODEL_MAP[self.mote_model_str]['name']
self.reconnect_button['state'] = 'disabled'
self.scan_button['state'] = 'active'
self.monitor_com = True
这会产生线程以监视COM端口。该线程在应用程序的__ Init __
建立初始连接并用某些命令准备硬件后,就可以在应用程序的__ INT __
上产生。
def spawn_com_monitor_thread(self):
self.com_monitor_thread = threading.Thread(target=self.com_monitor)
self.com_monitor_thread.daemon = True
self.com_monitor_thread.name = 'com monitor'
self.com_monitor_thread.start()
最后,这是在线程中运行的实际功能,该功能可监视COM端口。它只是不断地抓住开放的com端口,并检查我们使用的com端口是否存在。如果没有,它应该显示一个弹出窗口,设置标志,然后允许用户单击重新连接按钮。然后,重新连接函数应再次设置标志。这是为了防止用户重新连接时无限弹出。
def com_monitor(self):
while True:
ports = [port[0] for port in list(list_ports.comports())]
if (self.com_port not in ports) and (self.monitor_com == True):
with self.lock:
self.monitor_com = False
self.scan_button['state'] = 'disabled'
msg.showerror(title='Serial connection died', message='The serial cable has become disconnected. Scanning has been stopped. Please reconnect the cable and reconnect to the mote.')
self.reconnect_button['state'] = 'active'
self.monitor_com = False
我一直在敲几天,没有解决方案。我以前没有做太多的线程,并且想以螺纹方式进行此操作以允许最大的响应能力。
我正在运行Python 3.6.13。
I have a Tkinter app which connects to a proprietary sensor over serial and controls it with Python. I am trying to have a thread which always runs in the background to detect if the connection dies, shows an alert, and allows the user to press a button to re-establish the serial connection (reconnect is also done in another thread). For some reason, the COM monitor thread works fine, and when I unplug the serial cable, it shows a popup and enables the reconnect button as expected, but when I reconnect one or twice, the reconnect thread just stops releasing the lock. I've checked this with print statements.
Here is the code which spawns the thread that does the actual reconnect over serial. This thread is spawned when the reconnect button is pressed.
def spawn_reconnect_to_mote_thread(self):
self.reconnect_thread = threading.Thread(target=self.reconnect_to_mote)
self.reconnect_thread.daemon = True
self.reconnect_thread.name = 'reconnect'
self.reconnect_thread.start()
Here is the reconnect function. We also use a proprietary control software written in python which is why the syntax may look weird. This software has its own thread that is spawned when a connection is made. MOTE_MODEL_MAP just maps the correct control functions to the correct model ID which allows this to be easily extended to different hardware models.
def reconnect_to_mote(self):
with self.lock:
self.connection.close()
self.connection = MOTE_MODEL_MAP[self.mote_model_str ['mote_transport'].Connection({'serial': [self.com_port]})
self.com_model_label['text'] = MOTE_MODEL_MAP[self.mote_model_str]['name']
self.reconnect_button['state'] = 'disabled'
self.scan_button['state'] = 'active'
self.monitor_com = True
This spawns the thread to monitor the COM port. This thread is spawned pretty early on in the app's __init__
once the initial connection is made and the hardware is prepped with some commands.
def spawn_com_monitor_thread(self):
self.com_monitor_thread = threading.Thread(target=self.com_monitor)
self.com_monitor_thread.daemon = True
self.com_monitor_thread.name = 'com monitor'
self.com_monitor_thread.start()
Lastly, this is the actual function running in the thread which monitors the COM port. It just constantly grabs open COM ports and checks if the one we're using exists. If not, it should show a popup, set a flag, and allow the user to click the reconnect button. The reconnect function should then set the flag again. This is to prevent infinite popups while a user reconnects.
def com_monitor(self):
while True:
ports = [port[0] for port in list(list_ports.comports())]
if (self.com_port not in ports) and (self.monitor_com == True):
with self.lock:
self.monitor_com = False
self.scan_button['state'] = 'disabled'
msg.showerror(title='Serial connection died', message='The serial cable has become disconnected. Scanning has been stopped. Please reconnect the cable and reconnect to the mote.')
self.reconnect_button['state'] = 'active'
self.monitor_com = False
I've been banging my head on this for a couple days now with no solution. I haven't done much threading before and would like to do this in a threaded way to allow for maximum responsiveness.
I am running Python 3.6.13.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论