promotion image of download ymail app
Promoted

Dynamic Control Array (VB.NET)

這是一個在Run time建立Control aray的範例

以下數字為P4-2.8 DDR-400 1G所跑的結果

物件數 / 秒數

50->0.063

100->0.094

200->0.218

300->0.36

400->0.5155

500->0.61

600->0.922

700->0.938

800->1.453

900->1.781

1000->2.156

2000->7.469

3000->15.562

4000->26.656

5000->41.391

我的問題是:

為何物件數值越高時,所需「平均」執行時間越長(時間/物件數)?

5000個物件的平均時間是50個物件時的6.57倍(所花時間/物件數量)

不同的物件數上執行的結果發現,當物件數大於700或800左右時

平均時間將逐漸上升

● 為何會如此呢?

● 是否VB.NET在超大量的物件陣列當中會有特別耗資源的地方?

● 若是需要大量物件時應如何避免此問題呢?

程式:

在VB.NET開一個以"Form1"為名之Web Form

將下列程式Copy後即可執行(不需其他設定)

--------------------------------------------------------------------------

Dim but() As Button

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim iteam, bheight, bwidth, column, idx, margin, X, Y As Integer

Dim t As Date

Dim D1, D2 As Double

t = System.DateTime.Now : D1 = t.Minute * 60 + t.Second + t.Millisecond / 1000

'★☆★☆★☆請依序改此變數以測試不同物件數量值★☆★☆★☆

iteam = 50

'★☆★☆★☆請依序改此變數以測試不同物件數量值★☆★☆★☆

margin = 3 : column = 25 : bheight = 25 : bwidth = 28

With Me

Height = 600 : Width = 800

Top = (Screen.PrimaryScreen.Bounds.Height - 600) / 2

Left = (Screen.PrimaryScreen.Bounds.Width - 800) / 2

End With

ReDim but(iteam - 1)

For idx = 0 To UBound(but)

X = idx Mod column

Y = idx \ column

but(idx) = New Button

Me.Controls.Add(but(idx))

but(idx).Height = bheight

but(idx).Width = bwidth

but(idx).Text = (idx + 1).ToString

but(idx).TextAlign = ContentAlignment.MiddleCenter

but(idx).Font = New Font(but(idx).Font.Name, 8)

but(idx).Left = X * (bwidth + margin) + 10

but(idx).Top = Y * (bheight + margin) + 10

AddHandler but(idx).Click, AddressOf Me.but_Click

AddHandler but(idx).MouseMove, AddressOf Me.but_MouseMove

AddHandler but(idx).MouseLeave, AddressOf Me.but_MouseLeave

Next

t = System.DateTime.Now : D2 = t.Minute * 60 + t.Second + t.Millisecond / 1000

D2 = D2 - D1 : MsgBox(D2.ToString, , "Total Time")

End Sub

Private Sub but_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

MsgBox("Index = " + Me.Controls.GetChildIndex(sender).ToString, , "Index")

End Sub

Private Sub but_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

but(Me.Controls.GetChildIndex(sender) - 0).BackColor() = Color.Red

End Sub

Private Sub but_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)

but(Me.Controls.GetChildIndex(sender) - 0).BackColor() = Color.FromKnownColor(KnownColor.Control)

End Sub

-------------------------------------------------------------------------

感謝各位大大協助

Update:

感謝[龍]大大詳細的解說

但是我還有兩個疑問

1 我雖然在程式一開始宣告 動態陣列 Dim but() As Button

 但是接著立即在Run time時 給陣列大小

 iteam = 50

 ReDim but(iteam - 1)

 我的作法是在Run time時一次給足陣列所需的數據,並不是一次加一點

 為何也會如此呢?

2 有何方式可以改善呢?

Update 2:

我在一開頭就設定but的值也是相同的情形耶

我在想應該這幾行是關鍵

but(idx) = New Button

Me.Controls.Add(but(idx))

不太清楚為何new一個物件然後塞進來後就會產生極大的資源耗損

另外Item的數字是5000時就感覺到整個視窗產生非常嚴重的殘影

雖然大部分的物件是不在視窗上面的

2 Answers

Rating
  • Lv 7
    1 decade ago
    Favorite Answer

    VB裡Control Array使用記憶體的方法跟C++裡vector差不多. 他們都是1. 在宣告時已有一組記憶體可用2. 若在使用時遇到記憶體不夠時, 會自動要記憶體.3. 要記憶體時是把原先有的記憶體跟新增的記憶體一起要.4. 要到了之後再把原先記憶體裡的值拷貝進新的記憶體.5. 每次要記憶體時會比前一次要的多.例如, Control Array一開始有10個記憶體. 當使用者要用第11個時, Control Array會要10 + 10個. 要到之後先把前十個拷貝過來. 當使用者要用第21個時, Control Array會再要20+30個… 由此類歸. 因此你用的越多, 時間就越長, Control Array所用的記憶體也就越多(不是你用的).不過如把所使用的物件數和平均執行時間做成比例的話, 此法亦算是個好方法.懂不懂?不懂請再問------------------------------------------------我以上所講的是指Me.Controls.Add(but(idx))裡的Control Array.你一開始沒宣告but的大小.而你在執行時只重新宣告but一次而已.所以重新宣告but所佔的時間是個常數.你程式所需「平均」執行時間跟著iteam而變是因為Me.Controls.Add(but(idx))所需「平均」執行時間會跟著iteam而變.不過在重新宣告but時也是經過同樣的步驟.有一解,就是在第一次宣告but的大小宣告多一點.不過如用不完就浪費了.懂不懂?不懂請再問------------------------------------------------new並不會因iteam增大而花費更多時間.但是加入Me.Controls時會因iteam增大而花費更多時間.因每加入一個物體Me.Controls要確保Me.Controls裡有地方可容納要加入的物體.加入的物體越多,Me.Controls所佔的記憶體就越大.視窗殘影是因為每加一個物體Windows就要多畫一個物體.(畫完之後還要refersh)所以iteam越大,視窗殘影越大.懂不懂?不懂請再問------------------------------------------------你若把Me.Controls.Add(but(idx))拿掉.你程式所需「平均」執行時間舊差不多一樣了.(idx + 1).ToString X = idx Mod column Y = idx \ column 這三個也會因為iteam增大而花費更多時間.不過應無Me.Controls.Add(but(idx))那麼顯耀

    2005-09-06 21:54:16 補充:

    那跟「平均」執行時間沒有關係吧?

    原來我誤解你的用意了... :)

    2005-09-08 10:16:42 補充:

    應與「平均」執行時間沒有關係,因每個button修改Proterty所用的時間應都差不多.

    耗時間應是

    Me.Controls.Add(but(idx))

    X = idx Mod column

    Y = idx \ column

    but(idx).Text = (idx + 1).ToString

    2005-09-08 10:17:16 補充:

    自己試的結果

    Source(s): Myself, .NET
    • Commenter avatarLogin to reply the answers
  • 1 decade ago

    還是有關呀,只是看起來VB處理Array記憶體管理的效率好像不錯

    但使用在物件陣列時,因為物件內部的處理方式導致效能問題

    使用繼承物件修改Proterty的方式提高效能(將相同動作先處理)

    但以5000物件為例平均時間還是比50多了3倍呀(這個還是沒解決)

    VB的Control物件沒原始碼,好像要避免在子物件大量動作

    不過我做訝異的是使用with / end with居然可提高效能

    所以我的撰寫習慣有時候還是要改一下

    過一陣子,也想研究一下C++的這一部份是如何

    • Commenter avatarLogin to reply the answers
Still have questions? Get your answers by asking now.