2014-05-08 68 views
0

是否有可能使用表中每列的線程更新TStringGrid?從德爾福的不同線程更新TStringGrid

我正在做每個線程內的一些計算,我想將它們添加到列,到目前爲止我有類似的東西,但有一個奇怪的錯誤。

當一個線程獲得其列中當前行的結果後,它會調用此過程。

procedure TAnimator.Iteration(Sender: TObject); 
begin 
    TMyClass.AddData(TEngine(Sender).Data, TEngine(Sender).ID, TEngine(Sender).IterationsCount); 
end; 

有時我會得到一個正確添加線程的所有數據的表。但是,我可能會得到一個表,其中某些列中的第一個值無法正確顯示。

|| Col 1 || Col 2 || Col 3 || Col 4 || 
|| 1 ||  ||  || 4 || 
|| 1 || 2 ||  || 4 || 
|| 1 || 2 || 3 || 4 || 
|| 1 || 2 || 3 || 4 || 
|| 1 || 2 || 3 || 4 || 
+1

如果不知道類型是什麼,很難回答這個問題。什麼是「表」。顯然,如果它是一個GUI控件,那麼更新必須從主線程yada yada yada完成。 –

+3

'TStringGrid'不是表格。這是一個可視化組件,因此不是線程安全的。如果不使用「同步」或「隊列」,則無法從線程訪問VCL組件,這意味着所有更新都發生在主線程的上下文中。這裏有幾十個關於線程和VCL組件的問題,以及在IDE中使用'File-> New-> Other-> Delphi Files-> Thread Object'時IDE添加到生成的源代碼塊中的大註釋塊主菜單。它也在[documentation](http://docwiki.embarcadero.com/RADStudio/XE6/en/Defining_Thread_Objects)中 - 請參閱代碼。 –

回答

5

A TStringGrid是一個視覺控制。視覺控件的線程規則是所有對視覺控件的訪問必須由主GUI線程完成。你打破了這個規則並且承受了後果。

您的解決方案是遵守規則。使用TThread.SynchronizeTThread.Queue來確保訪問可視控件的所有代碼都在主GUI線程上執行。

0

在單獨的線程上進行計算沒有問題。但是,您必須使用主線程的計算結果更新網格。

有2點非常簡單的方法:

  • 做所有的計算在一個線程中的整列。然後處理OnTerminate事件以更新所需列中的所有單元格。
  • 使用Synchronize()從您的線程更新網格的特定單元格每次有新的值可用。

這應該讓你開始。如果您在細節方面遇到問題,則存在涵蓋OnTerminateSynchronize的現有問題。如果您仍然卡住,請隨時提出另一個問題。