我创建了一个简单的 GUI 应用程序,并希望在工作线程而不是事件调度线程上运行长时间的操作,以保持 GUI 响应。
只要工作线程正在运行 python 函数,它就可以正常工作。但是,如果函数在 C++ 代码上执行某些操作,则 GUI 线程会阻塞,就好像在它而不是在工作线程上执行了延长的操作一样!
看起来好像有一些隐藏的锁阻止 GUI 线程与工作线程并行运行。
我怀疑它可能与正在使用的 UI 框架有关,所以我尝试了 TKinter 和 wxPython 并且两者都出现了问题。
我在 Windows 7 上使用 Visual Studio 2010 和 python 2.7.5
这是 C++ 代码:
注意:我也尝试过使用 Sleep(timeSec * 1000L) 进行非忙等待,具有相同的行为
#include<boost/python.hpp>
#include <ctime>
void busyWait(int timeSec) {
clock_t beginTime(clock());
while (clock() - beginTime < timeSec * 1000L);
}
using namespace boost::python;
BOOST_PYTHON_MODULE(BusyCpp) {
def("busyWait", &busyWait, "waits...");
}
这就是python代码
# Set the path to append the DLL to it
from Utils import ToolEnvironment
ToolEnvironment.useToolBinaries()
from threading import Thread
import Tkinter
import BusyCpp
class simpleapp_tk(Tkinter.Tk):
def __init__(self, parent):
Tkinter.Tk.__init__(self, parent)
self.waitPeriod = 5 # seconds
button1 = Tkinter.Button(self, text=u"Busy C++", command=self.OnBusyCppClick)
button1.place(x=20, y=20)
button2 = Tkinter.Button(self, text=u"Busy Python", command=self.OnBusyPyClick)
button2.place(x=20, y=60)
def OnBusyCppClick(self):
t = Thread(target=self.busyWaitCpp)
t.start()
print 'Started thread'
def OnBusyPyClick(self):
t = Thread(target=self.busyWaitPy)
t.start()
print 'Started thread'
def busyWaitCpp(self):
BusyCpp.busyWait(self.waitPeriod)
print 'Done waiting C++'
def busyWaitPy(self):
from time import time
beginTime = time()
while time() - beginTime < self.waitPeriod:
pass
print 'Done waiting python'
if __name__ == "__main__":
app = simpleapp_tk(None)
app.title('my application')
app.mainloop()
单击“Busy Python”按钮时,可以看到 GUI 响应(该按钮看起来未单击)并且这些打印输出按此顺序显示,其中“已启动线程”立即出现,正如预期的那样:
Started thread
Done waiting python
单击“Busy C++”按钮时,可以看到 GUI 没有响应(按钮在等待时看起来像被单击),并且这些打印输出按此顺序显示,其中两者仅在等待结束时出现:
Done waiting C++
Started thread
所以很明显,只有在工作线程完成工作后,GUI 线程才能打印“已启动线程”
知道如何克服这个线程问题吗?
谢谢