2

我正在使用 Python 自动化一些 Windows 的东西,使用 PIL 来截取屏幕截图等。问题是,有时,在某些功能的深处,我会做一个time.sleep(1),我与之交互的 GUI 应用程序会在那一秒钟内冻结。这很奇怪,因为time.sleep在其他地方做不会导致冻结。我无法确切地确定是什么导致了冻结,什么没有。它发生在除主线程之外的线程和主线程中。

有任何想法吗?我觉得我只需要一个“放松”功能来让 Python 停止它正在做的任何事情,让目标 UI 恢复并刷新和处理输入,然后将其带回 Python。什么功能会做到这一点?(windowsSleep函数似乎就像 python 的一样time.sleep。)

4

3 回答 3

1

您可能不希望当前线程休眠,而是让应用程序有机会处理其消息。

由于很难委派给应用程序的主消息泵,传统上大多数长时间运行的任务都调用它们自己的临时消息泵

def process_messages():
    msg = wintypes.MSG ()
    while user32.GetMessageA (byref (msg), None, 0, 0) != 0:  
        user32.TranslateMessage (byref (msg))
        user32.DispatchMessageA (byref (msg))

微软祝福的版本在这里。代码会将事件传递给启动线程的应用程序的事件循环,并在事件队列为空时返回。

我在 Python 和第三方库中查找了一些功能的实现,但在如此快速的搜索中没有找到它。

简而言之,您应该在调用自己的process_messages()函数时执行上述操作,就像在 Visual Basic 和其他几种仅限 Windows 的语言中所做的那样,并避免调用sleep().

ps 您可以调整消息泵以仅在您等待的任务完成之前泵送消息。

于 2011-03-19T01:18:12.603 回答
1

我觉得我只需要一个“放松”功能来让 Python 停止它正在做的任何事情,让目标 UI 恢复并刷新和处理输入,然后将其带回 Python。什么功能会做到这一点?

调用sleep()(它的任何变体)将阻止您调用它的线程的执行。如果您希望在该线程中拥有响应式 UI,这只是您想要做的最后一件事。简而言之,一旦你睡着了,你什么都做不了!

当您有无响应的用户界面时,这表明一个长时间运行的任务正在处理 UI 的线程中执行,或者 UI 线程正在阻塞。因此,要遵循逻辑,如果您的 1 秒睡眠(它们实际上是打瞌睡,而不是正常的睡眠!)导致 UI 挂起,它们必须发生在与 UI 相同的线程中,或者 UI 所在的线程中等待。

我真的不知道您如何使用 PIL 以及您如何与您正在抓取其图像的应用程序进行交互,但您似乎不太可能将其注入其他进程。所以我猜这个进程正在等待你的线程。如果是这样,那么解决您的问题就没有真正的捷径。你只需要花更少的时间去做你正在做的事情。打电话sleep()只会让事情变得更糟。

打电话SwitchToThread()也帮不上什么忙。它所要做的就是允许另一个线程运行(如果有一个等待并准备好运行),但您希望您所在的线程运行。无论如何它不会有太大的不同,因为系统会知道你的线程想要运行,并会在适当的时候再次安排它。

底线是您的代码在阻止该进程的 UI 进程中运行。您只需要尽快让它发生,以尽量减少干扰。

于 2011-03-17T23:05:27.007 回答
0

SwitchToThread,看起来很有希望。或者用 Python 术语来说,ctypes.windll.kernel32.SwitchToThread().

编辑:嗯似乎不太这样做......

于 2011-03-17T22:48:25.030 回答