Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与spinbox控制变量一起使用时出现Python线程错误_Python_Multithreading_Locking - Fatal编程技术网

与spinbox控制变量一起使用时出现Python线程错误

与spinbox控制变量一起使用时出现Python线程错误,python,multithreading,locking,Python,Multithreading,Locking,在各种教程和在线参考资料之间来回浏览之后,终于让我的第一个线程脚本“稍微”运行起来。“有点”,因为我在启动过程中仍然会遇到一些奇怪的错误 我的课程目标 使用tkinter构建的集成上/下计数器GUI。(Python 3.4.2) Spinbox作为用户入口点-用户输入“目标”整数 或者单击其上/下箭头 当标签上的数字递增时,在标签上显示延迟更新/ 向下,以满足(2)中提到的“目标”整数 当标签上显示的数字等于 目标值 用户输入目标值后,一个“Go”(开始)按钮开始爬升/下降 停止更新的“停止”按

在各种教程和在线参考资料之间来回浏览之后,终于让我的第一个线程脚本“稍微”运行起来。“有点”,因为我在启动过程中仍然会遇到一些奇怪的错误

我的课程目标

  • 使用tkinter构建的集成上/下计数器GUI。(Python 3.4.2)
  • Spinbox作为用户入口点-用户输入“目标”整数 或者单击其上/下箭头
  • 当标签上的数字递增时,在标签上显示延迟更新/ 向下,以满足(2)中提到的“目标”整数
  • 当标签上显示的数字等于 目标值
  • 用户输入目标值后,一个“Go”(开始)按钮开始爬升/下降
  • 停止更新的“停止”按钮随时暂停爬升/下降 在达到目标值之前
  • 在这个简化的调试实现中,您将看到我似乎不必要地使用了spinbox控制变量。控制变量的实际(较长程序)应用于触发用户输入到spinbox的验证程序。实际上是控制变量在程序启动时给了我一些“奇怪的错误”

    我的简化代码如下:

    import tkinter as tk
    import threading
    import time
    
    class controlPanel():
        def __init__(self, master):
            self.root = master
            self.buildWidgets()
    
        def buildWidgets(self):
            self.labelVar = 0
            self.ctrlVar  = tk.StringVar()
            self.ctrlVar.set(str(self.labelVar))
            self.delay = 0.5
            #+++++++++++++++++++++++++++++++++
            self.labelName  = tk.Label(self.root, text="Current Value: ", padx=3, pady=3)
            self.labelName.grid(row=0, column=0)
            self.labelValue = tk.Label(self.root, text=str(self.labelVar), padx=3, pady=3)
            self.labelValue.grid(row=0, column=1)
            #+++++++++++++++++++++++++++++++++
            self.spinboxName = tk.Label(self.root, text="Target: ", padx=3, pady=3)
            self.spinboxName.grid(row=1, column=0)
            self.spinBoxA = tk.Spinbox(self.root, from_=0, to=1000,
                                       textvariable=self.ctrlVar,
                                       width=10, justify=tk.CENTER)
            self.spinBoxA.grid(row=1, column=1)
            #+++++++++++++++++++++++++++++++++
            self.goButton   = tk.Button(self.root, text="Go", width=12,
                                        command=self.goButtonFunction,
                                        padx=3, pady=3)
            self.goButton.grid(row=2, column=1)
            #+++++++++++++++++++++++++++++++++
            self.stopButton = tk.Button(self.root, text="Stop", width=12,
                                        command=self.stopButtonFunction,
                                        padx=3, pady=3)
            self.stopButton.grid(row=2, column=0)
            #+++++++++++++++++++++++++++++++++
            #self.labelValue.update()
            #self.spinBoxA.update()
            self.root.update()
    
        def goButtonFunction(self):
            print('GO button clicked')
            self.flgRun = True
    
        def stopButtonFunction(self):
            print('STOP button clicked')
            self.flgRun = False
    
    
    
    class controlThread(controlPanel):
        def __init__(self, master, name):
            self.root = master
            self.name = name
            controlPanel.__init__(self, self.root)
    
            self.flgRun     = False
            self.flgRunLock = threading.Lock()
            self.pollPeriod = 100 # polling period, in ms
    
            self.thread1 = threading.Thread(target = self.towardsTarget,
                                            name=self.name)
            self.thread1.daemon = False
            self.thread1.start()
            #time.sleep(5)
            self.pollFlgRun()
        #+++++++++++++++++++++++++++++++++
        def pollFlgRun(self): # polls self.flgRun every self.pollPeriod
            if self.flgRun:
                print('<< Entering pollFlgRun >>')
                time.sleep(0.01)
                self.towardsTarget()
                #self.flgRunLock.acquire() # lock thread to reset self.flgRun
                self.flgRun = False       # reset self.flgRun
                #self.flgRunLock.release() # release thread
            self.root.after(self.pollPeriod, self.pollFlgRun)
        #+++++++++++++++++++++++++++++++++    
        def towardsTarget(self):
            delay = 0.01  # delay in seconds
            time.sleep(delay)
    
            print('<< Entering towardsTarget >>')
    
            #self.flgRunLock.acquire()
            print('self.labelVar : ', str(self.labelVar))
                # Problem 1: the following reference to self.ctrlVar gave error everytime the
                # program starts. The error>> "RuntimeError: main thread is not in main loop"
                # subsequent click on controlPanel.goButton will still give the program behavior
                # specified above (i.e. no more error on subsequent clicks on the "Go" button)
                #
                # Problem 2: and when placed in a lock.acquire()/release() block, clicking the 
                # controlPanel.goButton will freeze up program 
            print('self.ctrlVar : ', self.ctrlVar.get()) 
            #self.flgRunLock.release()
    
            # test self.flgRun as well in case reset by controlPanel.stopButton
            while( self.flgRun and str(self.labelVar) != self.ctrlVar.get() ):
                print('WHILE loop')
                if( self.labelVar < int(self.ctrlVar.get()) ):
                    self.labelVar +=1
                    print('self.labelVar before sleep> ', self.labelVar)
                    time.sleep(delay)
                    print('self.labelVar AFTER sleep> ', self.labelVar)
                    self.labelValue["text"] = str(self.labelVar)
                    self.labelValue.update()
                else:
                    self.labelVar -=1
                    print('self.labelVar before sleep> ', self.labelVar)
                    time.sleep(delay)
                    print('self.labelVar AFTER sleep> ', self.labelVar)
                    self.labelValue["text"] = str(self.labelVar)
                    self.labelValue.update()
    
    
    
    if __name__ == '__main__':
        root = tk.Tk()
        ctrl = controlThread(root, "X-thread")
    
    将tkinter作为tk导入
    导入线程
    导入时间
    类controlPanel():
    定义初始(自我,主):
    self.root=master
    self.buildWidgets()
    def buildWidgets(自):
    self.labelVar=0
    self.ctrlVar=tk.StringVar()
    self.ctrlVar.set(str(self.labelVar))
    自延迟=0.5
    #+++++++++++++++++++++++++++++++++
    self.labelName=tk.Label(self.root,text=“当前值:”,padx=3,pady=3)
    self.labelName.grid(行=0,列=0)
    self.labelValue=tk.Label(self.root,text=str(self.labelVar),padx=3,pady=3)
    self.labelValue.grid(行=0,列=1)
    #+++++++++++++++++++++++++++++++++
    self.spinboxName=tk.Label(self.root,text=“Target:”,padx=3,pady=3)
    self.spinboxName.grid(行=1,列=0)
    self.spinBoxA=tk.Spinbox(self.root,从0到1000,
    textvariable=self.ctrlVar,
    宽度=10,对正=tk.中心)
    self.spinBoxA.grid(行=1,列=1)
    #+++++++++++++++++++++++++++++++++
    self.goButton=tk.Button(self.root,text=“Go”,width=12,
    命令=self.goButtonFunction,
    padx=3,pady=3)
    self.goButton.grid(行=2,列=1)
    #+++++++++++++++++++++++++++++++++
    self.stopButton=tk.Button(self.root,text=“Stop”,width=12,
    命令=self.stopButton函数,
    padx=3,pady=3)
    self.stopButton.grid(行=2,列=0)
    #+++++++++++++++++++++++++++++++++
    #self.labelValue.update()
    #self.spinBoxA.update()
    self.root.update()
    def GoButton功能(自身):
    打印('点击GO按钮')
    self.flgRun=True
    def停止按钮功能(自身):
    打印('单击停止按钮')
    self.flgRun=False
    类controlThread(控制面板):
    定义初始化(自身、主控、名称):
    self.root=master
    self.name=名称
    控制面板。初始化(self,self.root)
    self.flgRun=False
    self.flgRunLock=threading.Lock()
    self.pollPeriod=100#轮询周期,以毫秒为单位
    self.thread1=threading.Thread(target=self.towardsTarget,
    name=self.name)
    self.thread1.daemon=False
    self.thread1.start()
    #时间。睡眠(5)
    self.pollFlgRun()
    #+++++++++++++++++++++++++++++++++
    def pollFlgRun(self):#每self.pollgrun一次轮询self.flgRun
    如果self.flgRun:
    打印(“>”)
    睡眠时间(0.01)
    self.towardsTarget()
    #self.flgRunLock.acquire()#锁定线程以重置self.flgRun
    self.flgRun=False#重置self.flgRun
    #self.flgRunLock.release()#释放线程
    self.root.after(self.pollPeriod,self.pollFlgRun)
    #+++++++++++++++++++++++++++++++++    
    def towardsTarget(自):
    延迟=0.01#以秒为单位的延迟
    时间。睡眠(延迟)
    打印(“>”)
    #self.flgRunLock.acquire()
    打印('self.labelVar:',str(self.labelVar))
    #问题1:以下对self.ctrlVar的引用每次都出现错误
    #节目开始了。错误>>“RuntimeError:主线程不在主循环中”
    #随后单击controlPanel.goButton仍将给出程序行为
    #如上所述(即后续点击“Go”按钮时不再出现错误)
    #
    #问题2:当放置在lock.acquire()/release()块中时,单击
    #controlPanel.goButton将冻结程序
    打印('self.ctrlVar:',self.ctrlVar.get())
    #self.flgRunLock.release()
    #在控制面板复位的情况下,也测试self.flgRun.stop按钮
    while(self.flgRun和str(self.labelVar)!=self.ctrlVar.get()):
    打印(‘WHILE循环’)
    if(self.labelVar',self.labelVar)
    时间。睡眠(延迟)
    打印('self.labelVar AFTER sleep>',self.labelVar)
    self.labelValue[“text”]=str(self.labelVar)
    self.labelValue.update()
    其他:
    self.labelVar-=1
    打印('self.labelVar before sleep>',self.labelVar)
    时间。睡眠(延迟)
    打印('self.labelVar AFTER sleep>',self.labelVar)
    self.labelValue[“text”]=str(self.labelVar)
    自标定值