简体   繁体   中英

how to break a while loop immediately

I have this Class ScaleWorker

which is a worker running in a thread in the main interface
it contains receave_scaledata which waits for receaving data from a device and forward it to the interface
the function runs in a while loop with the condition while my_serial.is_open and self.continue_run:
with the function

def stop_me(self):
        self.continue_run = False

the function can be stopped when a signal is send from the main interface to execute stop_me
self.continue_run = True is switched to True and the loop breaks
at the end it emits self.finishedworking.emit() which tell the thread in the main interface to quit

self.scaleworker.finishedworking.connect(self.thread.quit)

The Problem is that the function receave_scaledata contains a function from pyserial
data_left = my_serial.inWaiting()
this function waits forever till it receaves data
without incoming data the other code gets not executed so when a signal is send to quit the thread the signal is stuck till data comes into the device and then the loop breaks

Im looking for a way to tell the worker to emit finishedworking right away without getting blocked So far I could not find a way around it

the code is a little bit hard to execute withpout the device but maybe you can help me

here is the Code

import sys
import time

import re
import serial
from serial.tools import list_ports

from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc



class ScaleWorker(qtc.QObject):

    work_signal = qtc.pyqtSignal(float)
    finishedworking = qtc.pyqtSignal()  # emmits that its finished

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.continue_run = False

    @qtc.pyqtSlot()
    def receave_scaledata(self):
        try:
            my_serial = serial.Serial(
                port="COM 3",
                baudrate=2400,
                bytesize=7,
                parity=serial.PARITY_NONE,
                timeout=None,
                stopbits=1,)

            if my_serial.is_open:
                print("serial open")

                while my_serial.is_open and self.continue_run:
                    data = my_serial.read()  # wait forever till data arives
                    time.sleep(1)  # hard delay to receave all bites
                    data_left = my_serial.inWaiting()  # wait forever
                    data += my_serial.read(data_left) # pack all receaved bites into on variable
                    self.work_signal.emit(data)
                self.finishedworking.emit()

        except serial.serialutil.SerialException:
            print("not open")

    def stop_me(self):
        self.continue_run = False




I simple yet robust way is to configure a rather short read timeout (~1 second) on the Serial port. You will just have to test whether len(data) == 0 and do not process further the (non) incoming data.

That way you can be sure to be able to test for the stop request at least on each occurence of the timeout.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM