Python线程class调用另一个线程class(队列帮助)

Python threaded class calls another threaded class (queue help)

我正在尝试使用 x-box 控制器控制 3 轴打印机。为了从 x-box 获取输入,我从 martinohanlon https://github.com/martinohanlon/XboxController/blob/master/XboxController.py 那里借用了代码 我还创建了逐行读取文本文件(G 代码)以移动打印机的代码。

我希望能够使用 X-Box 控制器 select 一个 G 代码文件和 运行 它,然后作为打印机 运行ning 继续监听取消按钮以防打印出错。 controller是线程化的class,我的readGcode是线程化的class.

我遇到的问题是,当我使用控制器启动 readGcode class 我无法与控制器通信,直到该线程完成。

我的临时解决方案是使用控制器 select 一个文件,然后将该文件路径传递给 readGcode class。在 readGcode class 中,它一直尝试使用 try 块打开文件并失败,直到文件路径可接受为止。然后它更改一个布尔值,使其跳过进一步阅读直到完成。

代码:

import V2_Controller as Controller
import V2_ReadFile as Read
import time
import sys
# file daialogue
import tkinter as tk
from tkinter import filedialog

# when X is selected on the x-box controller 
def X(xValue):
    if not bool(xValue):
        try:
            f=selectfile()
            rf.setfilename(f)
        except:
            print("failed to select file")

def selectfile():
    try:
        root = tk.Tk()  # opens tkinter
        root.withdraw()  # closes the tkinter window
        return filedialog.askopenfilename()
    except Exception:
        print("no file")

# setup xbox controller
xboxCont = Controller.XboxController(controlCallBack, deadzone=30, 
scale=100, invertYAxis=True)
# init the readfile class
rf = Read.Readfile()

# set the custom function for pressing X
xboxCont.setupControlCallback(xboxCont.XboxControls.X, X)

try:
    # start the controller and readfile threads
    xboxCont.start()
    rf.start()

    xboxCont.join()
    rf.join()

    while True:
        time.sleep(1)

# Ctrl C
except KeyboardInterrupt:
    print("User cancelled")

# error
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

finally:
    # stop the controller
    xboxCont.stop()
    rf.stop()

V2_Readfile

# Main class for reading the script
class Readfile(threading.Thread):

    # supports all variables needed to read a script
    class readfile:
        fileselect = True
        linecount = 0
        currentline = 0
        commands = []

    # setup readfile class
    def __init__(self):
        # setup threading
        threading.Thread.__init__(self)
        # persist values
        self.running = False
        self.reading = False

    def setfilename(self,filename):
        self.filename = filename

    # called by the thread
    def run(self):
        self._start()

    # start reading
    def _start(self):
        self.running = True
        while self.running:
            time.sleep(1)
            if not self.reading:
                try:
                    self.startread()
                except:
                    pass

    def startread(self):
        try:
            with open(self.filename, "r") as f:  # read a local file
                f1 = f.readlines()
                # run through each line and extract the command from each line
                linecount = 0
                line = []
                for x in f1:
                    # read each line into an array
                    line.append(x.split(";")[0])
                    linecount += 1

                # Store the variables for later use
                self.readfile.linecount = linecount
                self.readfile.commands = line
                self.reading = True
        except Exception:
            pass

        i = 0
        while i < self.readfile.linecount and self.reading:
            self.readfile.currentline = i + 1
            self.readline(i)
            i += 1

        # the following stops the code from reading again
        self.reading = False
        self.filename = ""


    def readline(self,line):
        Sort.sortline(self.readfile.commands[line])

    # stops the controller
    def stop(self):
        self.running = False

您可以使用像 threading.Event 这样的同步原语。

为此,您需要像这样修改 Readfile class:

from threading import Event


class Readfile(threading.Thread):

    # setup readfile class
    def __init__(self):
        # setup threading
        threading.Thread.__init__(self)
        # persist values
        self.running = False
        self.reading = False
        self.reading_file = Event()  # Initialize your event here it here

    def setfilename(self,filename):
        self.filename = filename
        self.reading_file.set()  # This awakens the reader

    def _start(self):
        self.running = True
        self.reading_file.wait()  # Thread will be stopped until readfilename is called
        self.startread()

另一个值得探索的同步原语是queue.Queue。如果您想处理多个文件名,它可能会很有用。

您在问题中描述的模式称为 Busy Waiting,应尽可能避免。