2013-05-04 59 views
0

我有一個線程調用某種形式的函數來更新此表單。任務完成後,使用Synchronize和結果形成線程更新,並且在程序運行時它可以正常工作。TForm創建和銷燬和線程的順序

問題發生在線程正在運行時,我關閉了程序我有訪問衝突。它是由已經發布的線程更新表單造成的。在重新排列表單創建順序(調用Application->CreateForm)之後,它正常工作,因爲現在持有線程代碼的表單將在更新的表單之前創建。看來,破壞的順序與創造秩序是相反的。

我還添加了一些代碼形式的析構函數,使如果形式與線程代碼的形式破壞之前確保線程終止。因此,在表單析構函數中重新排列表單創建順序和/或代碼可以解決問題。

但我有3個問題:

  1. 什麼是在創建表格的順序被破壞?我現在假設它是否與創建順序相反?

  2. 有沒有更好的辦法做到上述任務 - 線程處理完數據後,更新形式的GUI項目。現在我從線程本身使用Synchronize來完成它,但有經驗的線程可能會有更好的想法。其它我有一個想法是即使除去一束由編譯器生成CreateForm和手動創建它們,僅創建一個使用CreateForm破壞的更好的控制順序(由羅布肯尼迪的建議 - http://pages.cs.wisc.edu/~rkennedy/createform)主要形式。

  3. 典型應用程序中的動態表單創建/銷燬有多昂貴?使用表單隱藏並保存在內存中還是關閉時會更好?

+3

1)是的,以相反的順序銷燬2)車輪重新發明。最好重新排列邏輯3)取決於你設計的邏輯,可能會非常沉重。 – OnTheFly 2013-05-04 17:47:48

回答

3

當你創建一個帶有Owner一個組成部分,Owner增加您的組件被其擁有的組件列表。在此代碼中會發生這種情況:

procedure TComponent.Insert(AComponent: TComponent); 
begin 
    if FComponents = nil then FComponents := TList<TComponent>.Create; 
    FComponents.Add(AComponent); 
    if FSortedComponents <> nil then 
    AddSortedComponent(AComponent); 
    AComponent.FOwner := Self; 
end; 

正如您所看到的組件添加到列表的末尾。

當主人被摧毀,它調用DestroyComponents

procedure TComponent.DestroyComponents; 
var 
    Instance: TComponent; 
begin 
    FreeAndNil(FSortedComponents); 
    while FComponents <> nil do 
    begin 
    Instance := FComponents.Last; 
    if (csFreeNotification in Instance.FComponentState) 
     or (FComponentState * [csDesigning, csInline] = [csDesigning, csInline]) then 
     RemoveComponent(Instance) 
    else 
     Remove(Instance); 
    Instance.Destroy; 
    end; 
end; 

正如你所看到的,第一循環處理的最後一個成員。所以,組件以相反的順序銷燬。

我個人不會依賴銷燬命令。如果表單需要確保線程在表單被銷燬之前終止,我會在表單的析構函數中寫入代碼來執行該操作。

使用Synchronize卻是一個很好的解決很多問題。無論這是否是您問題的最佳解決方案,我都無法說出,因爲您尚未完全描述您的問題。

如何昂貴的是在典型的應用動態表單創建/銷燬?

不是很。通常顯示形式以響應用戶交互。程序可以創建表單的速度比用戶能夠處理的速度快得多。所以動態創建表單很少是一個問題。如果你想創建並摧毀數以千計的表單,這可能是一個問題。但那會很奇怪。