【发布时间】:2017-09-03 15:38:01
【问题描述】:
在带有delphi的android下,我有一个后台线程。在这个后台线程中,我调用了一个同步过程,只进行重绘:
TThread.Synchronize(nil,
procedure
begin
repaint;
end);
要恢复您的 delphi 源代码,在 android repaint 下只需将 bool 设置为 true,告诉主循环器在下一个循环中重新绘制表单:
procedure TPlatformAndroid.InvalidateWindowRect(const AForm: TCommonCustomForm; R: TRectF);
begin
TAndroidWindowHandle(AForm.Handle).NeedsUpdate := True;
end;
我的表单上还有一个 mousemove 事件,我捕捉到了鼠标移动,我也调用了重绘
procedure TMyFrame.FrameMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
VPos := Y;
repaint;
end;
我现在完全不明白,是为什么这个重绘(在后台线程中)会在动画中引起一些抖动如果(且仅当)i同时在屏幕上移动我的手指(如果我不移动手指,那么我没有抽搐)
这怎么可能?因为重绘只是简单地将通过鼠标移动(或反之亦然)已经为真的东西变为真。这如何将我的框架的 onpaint 调用延迟超过 100 毫秒(产生抽搐)。从后台线程中删除 onpaint 也删除了混蛋......不知道可能出了什么问题
注意:
如果在TPlatformAndroid.InternalProcessMessages 如果我替换
if TWindowManager.Current.RenderIfNeeds then
HasEvents := True
通过
TWindowManager.Current.RenderImmediately;
HasEvents := True;
然后滞后消失很多(但不是完全)
【问题讨论】:
-
所以你从线程内部一遍又一遍地调用
Synchronize?通话之间是否有任何延迟?还是他们只是背靠背?如果没有延迟,那么您的线程实际上是在阻止主线程实际上能够完成其工作。与设置布尔值无关,与使用Synchronize阻塞主线程有关。实际上,这是使线程与主线程通信的一种方式,但是如果您一直背靠背调用它,您就没有给主线程一个完成其工作的机会。至少延迟,但我不知道你为什么需要这个。 -
作为一个测试,如果你在
Synchronize中注释掉repaint会发生什么?你仍然观察到滞后吗? -
让我们说是,在这个例子中,一遍又一遍。不,它不能阻塞主线程,因为主循环 (TPlatformAndroid.InternalProcessMessages) 执行:processUImessage、Render、processTimerEvent 和 processsynchronize。由于渲染在任何情况下都需要大约 16 毫秒(opengl vsync),那么我们的同步(除了将布尔值设为 true 之外什么都不做)将每 16 毫秒(分钟)执行一次,因此不会影响动画
-
@JerryDodge :不,如果我评论重绘并让同步一切正常,不再滞后......我完全迷失了!
-
你问了很多非常不清楚的问题,而且没有一个是关于你试图解决的实际问题。似乎所有这些都是关于这个问题OpenGL : how to avoid jerks in scrolling / animations 你没有提供正确的minimal reproducible example。请访问help center 并详细了解该网站的工作原理,否则您将遇到困难。
标签: android delphi firemonkey