我有一个GUI应用程序,它使用子进程启动一些命令,然后通过从subprocess.Popen.stdout读取并使用wx.ProgressDialog来显示此命令的进度。我在Linux下编写了应用程序,它在那里完美运行,但我现在正在Windows下进行一些测试,似乎尝试更新进度对话框会导致应用程序挂起。没有错误消息或任何东西,所以我很难弄清楚发生了什么。以下是简化代码:
子进程在主线程中通过此方法在单独的线程中启动:
def onOk(self,event):
""" Starts processing """
self.infotxt.Clear()
args = self.getArgs()
self.stringholder = args['outfile']
if (args):
cmd = self.buildCmd(args, True)
if (cmd):
# Make sure the output directory is writable.
if not self.isWritable(args['outfile']):
print "Cannot write to %s. Make sure you have write permission or select a different output directory." %os.path.dirname(args['outfile'])
else:
try:
self.thread = threading.Thread(target=self.runCmd,args=(cmd,))
self.thread.setDaemon(True)
self.thread.start()
except Exception:
sys.stderr.write('Error starting thread')
这是runCmd方法:
def runCmd(self, cmd):
""" Runs a command line provided as a list of arguments """
temp = []
aborted = False
dlg = None
for i in cmd:
temp.extend(i.split(' '))
# Use wx.MutexGuiEnter()/MutexGuiLeave() for anything that accesses GUI from another thread
wx.MutexGuiEnter()
max = 100
stl = wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME | wx.PD_REMAINING_TIME
dlg = wx.ProgressDialog("Please wait", "Processing...", maximum = max, parent = self.frame, style=stl)
wx.MutexGuiLeave()
# This is for windows to not display the black command line window when executing the command
if os.name == 'nt':
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = subprocess.SW_HIDE
else:
si = None
try:
proc = subprocess.Popen(temp, shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except Exception:
sys.stderr.write('Error executing a command. ')
# Progress dialog
count = 0
while True:
line=proc.stdout.readline()
count += 1
wx.MutexGuiEnter()
if dlg.Update(count) == (True, False):
print line.rstrip()
wx.MutexGuiLeave()
if not line: break
else:
print "Processing cancelled."
aborted = True
wx.MutexGuiLeave()
proc.kill()
break
wx.MutexGuiEnter()
dlg.Destroy()
wx.GetApp().GetTopWindow().Raise()
wx.MutexGuiLeave()
if aborted:
if os.path.exists(self.stringholder):
os.remove(self.stringholder)
dlg.Destroy()
proc.wait()
再一次,这在Linux下工作正常,但在Windows上冻结。如果我删除dlg.Update()行,它也可以正常工作。子进程输出在主窗口中打印出来并显示ProgressDialog,只是进度条不移动。我错过了什么?
答案 0 :(得分:0)
请勿尝试使用wx.MutexGuiEnter
和wx.MutexGuiLeave
。您可以使用wx.CallAfter
处理从另一个线程更新GUI。我以前从未见过有人在wx应用程序中使用这些互斥锁,甚至没有在教程或使用线程的示例中使用过这些互斥锁。