2017-09-03 23 views
-1

在android下使用delphi,我有一個後臺線程。在這樣的背景線程我稱之爲同步的過程,只是做一個重繪:如何從後臺線程調用repaint可能會減慢動畫速度?

TThread.Synchronize(nil, 
    procedure 
    begin 
    repaint; 
    end); 

恢復你的Delphi源代碼,在Android的重繪簡單地把一個布爾真話說到主尺蠖上重繪形式下一個循環:

procedure TPlatformAndroid.InvalidateWindowRect(const AForm: TCommonCustomForm; R: TRectF); 
begin 
    TAndroidWindowHandle(AForm.Handle).NeedsUpdate := True; 
end; 

我也有我的窗體上的鼠標移動事件與我趕上鼠標移動和在那裏我也呼籲重繪

procedure TMyFrame.FrameMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); 
begin 
    VPos := Y; 
    repaint;  
end; 

現在我絕對不明白,是爲什麼這個repaint(在後臺線程)導致動畫一些混蛋如果(並且只有)我也同時移動我的手指在屏幕上(如果我不要動的手指,那麼我沒有混蛋)

這可能是怎麼可能的?因爲重繪只是通過鼠標移動來實現真實的事情(反之亦然)。這怎麼可以延遲一段時間超過100毫秒的調用我的框架(產生混蛋)。從後臺線程刪除刪除的OnPaint也抽筋......不知道什麼可能是錯誤的

注:

如果TPlatformAndroid.InternalProcessMessages如果我更換

if TWindowManager.Current.RenderIfNeeds then 
    HasEvents := True 

通過

TWindowManager.Current.RenderImmediately; 
HasEvents := True; 

然後滯後消失很多(但不完全)

+0

所以,如果你的線程中調用'Synchronize'一遍又一遍,你有什麼樣的呼叫之間的延遲或者他們」?只是bac k回來?如果沒有延遲,那麼你的線程基本上阻止了主線程實際上能夠完成它的工作。與設置布爾值無關,以及使用'Synchronize'阻塞主線程的一切。事實上,這是使線程與主線程進行通信的方式,但是如果您一直稱它爲主線程,則不會讓主線程有機會完成其工作。最起碼拖延了,但我不知道你爲什麼需要這個。 –

+0

作爲一個測試,如果你在'Synchronize'中註釋掉'repaint',會發生什麼?你還觀察到一個滯後? –

+0

在這個例子中,讓我們說一遍又一遍。不,它不能阻塞主線程,因爲主循環(TPlatformAndroid.InternalProcessMessages)會執行:processUImessage,Render,processTimerEvent和processsynchronize。作爲渲染採取16毫秒左右的任何情況下(opengl vsync),那麼我們的同步(沒有做任何事情不會使bool成爲真)將每16毫秒(分鐘)執行,所以沒有葡萄乾影響動畫 – andrey

回答

-1

好吧,我找出原因。

在delphi中的問題是,即使重繪是一個微不足道的操作,並將標誌設置爲true,下面的操作實際上可以呈現表單並不是微不足道的,無論如何(即使表單沒有改變)它將需要16毫秒(vsync信號罰款)。我的問題也與ui事件有關,因爲當它們是ui事件時,delphi每隔1 ms發送一個計時器而不是每10 ms

所以你可以理解,如果我在不好的時候調用repaint(例如通常必須先啓動計時器),那麼我們將有16ms的延遲等待,然後當計時器啓動時,它會太晚,我們已經有一幀丟失(實際上不是,但最後一次塗料什麼也沒做),然後我們將有滯後:(

也這是因爲這種錯誤的:https://quality.embarcadero.com/browse/RSP-18982