我发现我的Flex应用程序的UI在非常长的处理循环(几十秒)内变得没有响应。例如,在处理非常大的XML文件并对每个元素执行某些操作时...
是否有“ProcessMessages”的等价物?也就是说,一个调用会告诉Flex继续响应UI事件,即使是在一些长循环的中间,这样UI也不会没有响应?
我知道Flex是单线程设计。这就是我正在寻找像ProcessMessages()这样的函数的原因 单线程可重入 应用程序(如VB或基于单线程消息循环的C ++应用程序)在长时间运行期间保持响应。
答案摘要
- 没有类似的内置功能
HandleEvents()
要么 ProcessMessages()
在Flex中。
- 使用某种回调机制迭代地处理长计算过程的块,同时在块之间屈服于运行时,从而使其能够响应,是在长计算期间维持响应UI的唯一方法。
- 完成上述方法的方法是:
- 使用
enterFrame
event,只要Flex应用程序下面的Flash“movie”图层刷新其帧(类似于20fps),就会调用该事件。
- 使用计时器。
- 运用
UIComponent.callLater()
哪个计划工作要“以后”完成。 (作为文档 说: Queues 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.
- 使用故意触发的鼠标/键盘事件来创建伪“工作线程”,如 这个例子。
如果有进一步的建议,或者我遗漏了任何东西,请随时编辑这个(现在的)维基片。
问题是Flash是单线程的,即在代码的一部分运行之前,不能进行其他处理。你会以某种方式将处理分解成更小的块并执行这些块,比如说 enterFrame
事件。
编辑:我担心低估这个(或西蒙的)答案并没有改变这在AS3中不可行的事实。读 本文 有关问题的更多见解。该文章还包括一个名为PseudoThread的简单“库”,它有助于执行长背景计算。不过,你仍然需要将问题分解成更小的部分。
问题是Flash是单线程的,即在代码的一部分运行之前,不能进行其他处理。你会以某种方式将处理分解成更小的块并执行这些块,比如说 enterFrame
事件。
编辑:我担心低估这个(或西蒙的)答案并没有改变这在AS3中不可行的事实。读 本文 有关问题的更多见解。该文章还包括一个名为PseudoThread的简单“库”,它有助于执行长背景计算。不过,你仍然需要将问题分解成更小的部分。
我可以肯定地告诉你,从Flex 3开始,没有类似的内置结构 ProcessMessages
您正在描述的功能。
解决此问题的最常见方法是将正在处理的任何工作拆分为“工作”任务队列,并将“工作管理器”拆分为控制队列。当每个“worker”完成其处理时,worker队列管理器将下一个worker从队列中弹出并在a中执行 callLater()
调用。这将产生类似于“屈服于主线程”的效果,并允许您的UI接收事件并做出响应,同时仍允许在将控制权返回给工作者时继续处理。
一旦你有了这个工作,你可以做一些测试和分析,以确定你的应用程序是否可以在调用之前执行多个工作程序的运行 callLater()
,并将此逻辑封装在工作队列管理器中。例如,在我们的这种模式的实现中(队列中有几百个工作者),我们能够通过在“屈服于主线程”之前执行4个工作人员来更快地完成处理并具有可比较的感知性能 callLater()
,但这完全取决于工人正在做的工作的范围和性质。
ActionScript的流程模型是单线程的,所以答案是否定的。最好的办法是,如果可以的话,要么推迟服务器上的异步任务,要么在长循环运行时弹出等待光标,或者将你的进程分解成一些不那么具有侵入性的小块,或者执行在用户不太可能感觉到效果的时刻长时间运行的任务(例如app启动)。
Actionscript是单线程设计,没有任何downvoting答案会改变它。
为了兼容性,您最好的办法是尝试将处理拆分为更小的块,并迭代进行处理。
如果你绝对需要穿线它可以 有点 可以在Flash Player 10中使用 Pixel Bender 过滤器。这些将在一个单独的线程上运行,一旦完成就可以给你一个回调。
我相信它们非常适合“硬核”处理任务,因此它们可能很适合您的目的。
但是,它们会对您的代码提出另外一组要求,因此您可能更好地执行计算的小“桶”。
Flash Player中没有等效功能。按照设计,Flash Player在渲染到屏幕之间交替,然后为每个帧运行所有代码。运用 Event.ENTER_FRAME
显示对象上的事件,或 Timer
其他地方的对象,是打破很长时间计算的最佳选择。
值得注意的是,ActionScript中的某些事件有一个 updateAfterEvent()
功能与以下描述:
如果已修改显示列表,则指示Flash Player或AIR运行时在此事件处理完成后呈现。
尤其是, TimerEvent
, MouseEvent
,和 KeyboardEvent
支持 updateAfterEvent()
。可能还有其他人,但那些是我通过快速搜索找到的。