根本无法停止线程(除非我引起异常)
Can't stop thread at all (unless I cause an exception)
所以我正在开发一个 GUI (PyQt5),并且我是多线程的,以便能够同时进行数据采集和实时绘图。
长话短说,除了停止处理数据采集的线程外,一切正常,它不断循环并调用 PySerial 来读取 com 端口。当按下 GUI 上的按钮时,我想打破线程内的 while 循环以停止读取 com 端口并允许安全关闭 com 端口。
目前,我尝试过的 none 方法设法正常退出线程内的 while 循环,这会导致 PySerial 库出现各种错误,并且关闭的 com 端口/尝试在线程中读取。这是我尝试过的:
- 使用 class 变量 (
self.serial_flag
) 并在按下按钮时更改其状态。线程循环看起来像这样:while self.serial_flag:
- 使用全局变量(脚本顶部的
serial_flag = False
)。在线程函数的顶部定义 global serial_flag
和相同的条件:while serial_flag:
- 使用共享内存变量:
from multiprocessing import Value
,然后定义serial_flag = Value('i', 0)
,然后在循环中检查while serial_flag.value == 0:
- 使用
threading.Event
设置事件并将其用作中断条件。定义:serial_flag = threading.Event()
和线程内部 while 循环:if serial_flag.is_set(): break
None 这些似乎可以打破 while 循环,我保证我已经完成了研究此类事情的解决方案的功课 - 我觉得我做错了一些基本的事情我的多线程应用程序。以下是调用/处理线程的 GUI 部分(我最近尝试使用 threading.Event):
import threading, queue
serial_flag = threading.Event()
def serial_run_data(self):
cntr = 0
while True:
if serial_flag.is_set():
print("flag was set")
break
value = self.ser.read_until(self.EOL) # old EOL: \r\n, new: o\i
if len(value) == 21 and self.EOL in value:
self.queueRaw.put_nowait(value)
else:
print(value)
cntr = cntr + 1
if cntr == 50:
self.data_ready = True
cntr = 0
def start_plot(self): # Start/ Stop Button
# Start Button
if self.start_button.text() == 'START':
self.serial_setup()
if not self.error:
self.serial_flag = True
self.t = threading.Thread(target=self.serial_run_data)
self.t.start()
self.timer.start()
self.start_button.setText('STOP')
# Stop Button
elif self.start_button.text() == 'STOP':
if not self.error:
self.serial_flag = False
serial_flag.set()
self.timer.stop()
print(self.t.is_alive())
self.ser.close()
self.start_button.setText('START')
欢迎任何反馈(如果我提供的内容不够充分,我将制作一个可重现性最低的示例)。干杯!
出现此问题是因为您没有等待线程终止就关闭了串口。虽然您设置了事件,但可能无法访问那部分代码,因为从串行端口读取仍在发生。关闭串口时,串口库出错
你应该等待线程终止,然后关闭端口,你可以通过添加
self.t.join()
在 serial_flag.set()
之后。
所以我正在开发一个 GUI (PyQt5),并且我是多线程的,以便能够同时进行数据采集和实时绘图。
长话短说,除了停止处理数据采集的线程外,一切正常,它不断循环并调用 PySerial 来读取 com 端口。当按下 GUI 上的按钮时,我想打破线程内的 while 循环以停止读取 com 端口并允许安全关闭 com 端口。
目前,我尝试过的 none 方法设法正常退出线程内的 while 循环,这会导致 PySerial 库出现各种错误,并且关闭的 com 端口/尝试在线程中读取。这是我尝试过的:
- 使用 class 变量 (
self.serial_flag
) 并在按下按钮时更改其状态。线程循环看起来像这样:while self.serial_flag:
- 使用全局变量(脚本顶部的
serial_flag = False
)。在线程函数的顶部定义global serial_flag
和相同的条件:while serial_flag:
- 使用共享内存变量:
from multiprocessing import Value
,然后定义serial_flag = Value('i', 0)
,然后在循环中检查while serial_flag.value == 0:
- 使用
threading.Event
设置事件并将其用作中断条件。定义:serial_flag = threading.Event()
和线程内部 while 循环:if serial_flag.is_set(): break
None 这些似乎可以打破 while 循环,我保证我已经完成了研究此类事情的解决方案的功课 - 我觉得我做错了一些基本的事情我的多线程应用程序。以下是调用/处理线程的 GUI 部分(我最近尝试使用 threading.Event):
import threading, queue
serial_flag = threading.Event()
def serial_run_data(self):
cntr = 0
while True:
if serial_flag.is_set():
print("flag was set")
break
value = self.ser.read_until(self.EOL) # old EOL: \r\n, new: o\i
if len(value) == 21 and self.EOL in value:
self.queueRaw.put_nowait(value)
else:
print(value)
cntr = cntr + 1
if cntr == 50:
self.data_ready = True
cntr = 0
def start_plot(self): # Start/ Stop Button
# Start Button
if self.start_button.text() == 'START':
self.serial_setup()
if not self.error:
self.serial_flag = True
self.t = threading.Thread(target=self.serial_run_data)
self.t.start()
self.timer.start()
self.start_button.setText('STOP')
# Stop Button
elif self.start_button.text() == 'STOP':
if not self.error:
self.serial_flag = False
serial_flag.set()
self.timer.stop()
print(self.t.is_alive())
self.ser.close()
self.start_button.setText('START')
欢迎任何反馈(如果我提供的内容不够充分,我将制作一个可重现性最低的示例)。干杯!
出现此问题是因为您没有等待线程终止就关闭了串口。虽然您设置了事件,但可能无法访问那部分代码,因为从串行端口读取仍在发生。关闭串口时,串口库出错
你应该等待线程终止,然后关闭端口,你可以通过添加
self.t.join()
在 serial_flag.set()
之后。