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

时间:2018-10-01 22:00:47

标签: python multithreading controller queue xbox

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

我希望能够使用X-Box控制器选择一个G代码文件并运行它,然后在打印机运行时继续监听取消按钮,以防万一打印出错。控制器是一个线程类,而我的readGcode是一个线程类。

我遇到的问题是,当我使用控制器启动readGcode类时,直到该线程完成,我才能与控制器通信。

我的临时解决方案是使用控制器选择一个文件,然后将该文件路径传递给readGcode类。在readGcode类中,它会继续尝试使用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

1 个答案:

答案 0 :(得分:0)

您可以使用threading.Event之类的同步原语。

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

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,应尽可能避免使用。