在长循环期间,Flex等效于ProcessMessages和无响应的UI

时间:2009-02-18 10:08:45

标签: flex user-interface

我发现我的Flex应用程序的UI在很长的处理循环(几十秒)内变得没有响应。例如,在处理非常大的XML文件并对每个元素执行某些操作时......

是否有“ProcessMessages”的等价物?也就是说,一个调用会告诉Flex继续响应UI事件,即使在一些长循环的中间,这样UI也不会没有响应?

我知道Flex是单线程设计。这就是为什么我正在寻找像ProcessMessages()这样的函数 - 一个允许单线程可重入应用程序(如在VB中,或基于单线程消息循环的C ++应用程序)的函数在长时间内保持响应操作。

答案摘要

  1. Flex中没有内置函数,例如HandleEvents()ProcessMessages()
  2. 使用某种回调机制迭代地处理长计算过程的块,同时在块之间屈服于运行时,从而使其能够响应,是在长计算期间维护响应UI的唯一方法。
  3. 完成上述工作的方法是:
    1. 使用enterFrame事件,只要Flex应用程序下面的Flash“影片”图层刷新其帧(类似于20fps),就会调用该事件。
    2. 使用计时器。
    3. 使用UIComponent.callLater()安排工作“稍后”完成。 (作为文档sayQueues a function to be called later. Before each update of the screen, Flash Player or AIR calls the set of functions that are scheduled for the update.
    4. 使用有意触发的鼠标/键盘事件来创建伪“工作线程”,如this example
  4. 如果有进一步的建议,或者我遗漏了任何内容,请随时编辑此(现在)维基片。

5 个答案:

答案 0 :(得分:6)

问题是Flash是单线程的,即在代码的一部分运行之前,不能进行其他处理。你会以某种方式将处理分解成更小的块,并在enterFrame事件上执行这些块。

编辑:我担心低估这个(或西蒙的)答案并不会改变这在AS3中无法实现的事实。阅读this article,了解有关该问题的更多信息。该文章还包括一个名为PseudoThread的简单“库”,它有助于执行长背景计算。不过,你仍然需要将问题分解成更小的部分。

答案 1 :(得分:4)

我可以肯定地告诉你,从Flex 3开始,没有类似于你所描述的ProcessMessages功能的内置结构。

解决此问题的最常见方法是将正在处理的任何工作拆分为“工作”任务队列和“工作管理器”以控制队列。当每个“worker”完成其处理时,worker队列管理器会弹出队列中的下一个worker并在callLater()调用中执行它。这将产生类似于“屈服于主线​​程”的效果,并允许您的UI接收事件并做出响应,同时仍然允许在将控制权返回给工作者时继续处理。

一旦你有了这个工作,你可以做一些测试和分析,以确定你的应用程序是否可以在调用callLater()之前执行多个工作程序的运行,并将此逻辑封装在工作队列中经理。例如,在我们的这种模式的实现中(队列中有几百个工作者),我们能够通过执行4个工作人员在“屈服于主线​​程”{{{{ 1}},但这完全取决于你的工人正在做的工作的范围和性质。

答案 2 :(得分:2)

ActionScript的流程模型是单线程的,所以答案是否定的。最好的办法是,如果可以的话,要么推迟服务器上的异步任务,要么在长循环运行时弹出一个等待光标,或者将你的进程分解成一些不那么具有侵入性的小块,或者执行当用户不太可能感受到效果时(例如,应用启动),长时间运行的任务。

答案 3 :(得分:2)

Actionscript是单线程设计,没有任何downvoting答案会改变这一点。

为了兼容性,您最好的办法是尝试将处理拆分为更小的块,然后迭代进行处理。

如果您绝对需要线程,则可以使用Pixel Bender过滤器在Flash Player 10中完成排序。这些将在一个单独的线程上运行,一旦完成就可以给你一个回调 我相信它们非常适合“硬核”处理任务,因此它们可能很适合您的目的。 但是,它们会对您的代码提出另外一组要求,因此您可能更好地进行计算的小“桶”。

答案 4 :(得分:1)

Flash Player中没有等效功能。按照设计,Flash Player在渲染到屏幕之间交替,然后为每个帧运行所有代码。在显示对象上使用Event.ENTER_FRAME事件,或在其他地方使用Timer个对象,是打破很长时间计算的最佳选择。

值得注意的是,ActionScript中的某些事件具有updateAfterEvent()函数,其描述如下:

  

如果已修改显示列表,则指示Flash Player或AIR运行时在此事件处理完成后呈现。

特别是,TimerEventMouseEventKeyboardEvent支持updateAfterEvent()。可能还有其他人,但这些是我通过快速搜索找到的。