2016-03-07 45 views
-1

我試圖在for循環中創建圖片框,然後將它們添加到我的主窗體中。我在另一個線程中創建圖片框來減少加載時間,但是我的應用程序不斷崩潰。從線程添加圖片框到窗體

我將代碼更改了10次,實際版本看起來像這樣。

Private letters() As PictureBox 

Private Sub loadLetters() 
    Dim j As Integer = 0 
    letters = New PictureBox() {} 
    For value As Integer = 0 To 7 
     letters(value).Image = ImageList1.Images(value + 8) 
     letters(value).Name = "picLetter_" & value + 8 
     letters(value).Location = New Point(0, j) 
     letters(value).Size = New Size(100, 100) 
     letters(value).Visible = True 
     j = j + 100 

     Me.BeginInvoke(New MethodInvoker(AddressOf loadLetters)) 
    Next 
End Sub 

我的另一個嘗試把我帶到這個:

If Me.InvokeRequired Then 
    Dim d As New updateMain(AddressOf loadLetters) 
    Me.Invoke(d, New Object() {letters(value)}) 
Else 
    Me.Controls.Add(letters(value)) 
End If 

Private Delegate Sub updateMain(ByVal picture As PictureBox) 

如何從另一個線程添加圖片框的主要形式?

+0

您無法在非UI線程上創建控件。所有UI元素都必須在UI線程上創建,否則會出錯。你可以在後臺線程上做的唯一事情就是非UI處理或加載數據。你爲什麼試圖在後臺線程上創建它們? – Enigmativity

+0

@Enigmativity:你錯了。我只是測試了他和我的代碼(在他的最後幾次初始化修正之後),並且從另一個線程(我正在使用.NET 4.0)完全正常工作。由於它們作爲變量添加到數組中,因此可以從任何線程訪問該數組,因爲它們尚未添加(也未用於)任何容器。 –

+0

@VisualVincent - 對不起,您可以從非UI線程創建儘可能多的UI元素,只要不將它們附加到顯示的UI容器即可。 – Enigmativity

回答

0

您一直在調用相同的方法,這意味着每次調用時都嘗試創建八個附加圖片框。持續不斷的調用最終會導致StackOverflow異常,因爲您試圖創建無限量的圖片框。

你必須創建一個單獨的方法來添加圖片框只有,讓你的主要方法創建它們,並單獨的方法將它們添加到窗體。現在

Private Delegate Sub AddPictureBoxDelegate(ByRef PBox As PictureBox) 
'ByRef is better to use when not creating a copy of the PictureBox (and when you're not going to modify it as a separate one). 

Private Sub AddPictureBox(ByRef PBox As PictureBox) 
    If Me.InvokeRequired = True Then 'Invocation is required. 
     'Call the method again, using invocation. 
     Me.Invoke(New AddPictureBoxDelegate(AddressOf AddPictureBox), PBox) 
    Else 'No (further) invocation required. 
     Me.Controls.Add(PBox) 
    End If 
End Sub 

,在你的線程您只要致電:

AddPictureBox(letters(value)) 

和預期的一樣正常工作了。

+0

願意解釋一下嗎?還是由於對這個問題的評論? –

+0

調用'.Invoke'來添加已經在非UI線程上創建的UI元素只是要求麻煩。用戶界面元素需要在用戶界面線程上創建,因此提供的建議很差。 OP可能會發現這表面上是成功的,但是會有一些操作會導致它崩潰。另外,絕對不需要在參數'ByRef'中調用這個函數。最後,OP必須有一些理由認爲在另一個線程上創建UI元素是一個很好的理想。我認爲在提供答案之前應該確定這一點。 – Enigmativity

+0

@Enigmativity:根據他的帖子,他想(或至少據我瞭解)「減少加載時間」。我知道通過不同線程創建/處理控件是一個糟糕的主意,但是由於我已經測試過它,並且沒有錯誤,所以我認爲在這種情況下沒有問題。圖片框在內存中創建並綁定到變量。之後他們再也不用那個線程了。這是因爲您可以通過多線程讀取/修改整數,字符串等,因爲它們不是專門綁定到該線程的。 –