我正在尝试使用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
答案 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,应尽可能避免使用。