I have an application that refreshes data every 30 seconds. On the main page, a dynamic control is added for each item of data. When the timer gets triggered, the controls are disposed, set to nothing, and the tab page is cleared.
The problem is that they do no dispose, private bites keep building with every refresh. Around 70mb private bytes, the application crashes with Message=Error creating window handle. NativeErrorCode=1158. It can be any control on the form that gets the error.
Tried using System.GC.Collect(), overriding Dispose on the control, and many other techniques that I have found related to this issue.
I do not think Dispose or Garbage collect actually work. This is the sub that clears the controls.
Revised code (simplified):
Sub ClearHotLists()
For i As Int16 = ControlCollection.Count - 1 To 0 Step -1
ControlCollection(i).Dispose()
Next
End Sub
Private Sub TimerHotList_Tick(sender As Object, e As EventArgs) Handles TimerHotList.Tick
PopulateHotList(False)
End Sub
Sub PopulateHotList(Connect)
ClearHotLists()
ControlCollection.Clear()
Dim hpos As Int16 = 10
Dim vpos As Int16 = 10
If Connect Then sqlConn.Open()
sqlConn3.Open()
Select Case Me.tcMain.SelectedIndex
Case 0
AddHotListItems("Ground", hpos, vpos, Me.tabShipping)
vpos += 230 : hpos = 10
AddHotListItems("Hand Carry", hpos, vpos, Me.tabShipping)
vpos += 230 : hpos = 10
AddHotListItems("Red", hpos, vpos, Me.tabShipping)
vpos += 230 : hpos = 10
AddHotListItems("Outside Vendor", hpos, vpos, Me.tabShipping)
Case 1
hpos = 10 : vpos = 10
For i As Int16 = 0 To InspCnt - 1
AddHotListItems(InspArr(i), hpos, vpos, Me.tabInspection)
vpos += 230 : hpos = 10
Next
Case 2
hpos = 10 : vpos = 10
For i As Int16 = 0 To DebCnt - 1
AddHotListItems(DebArr(i), hpos, vpos, Me.tabDeburring)
vpos += 230 : hpos = 10
Next
End Select
sqlConn3.Close()
If Connect Then sqlConn.Close()
End Sub
Sub AddHotListItems(ByVal ItemType As String, ByRef hpos As Int16, ByRef vpos As Int16, ByVal Tab As TabPage)
Dim DynHotListItem As HotListItem
Dim ControlObject As Control
sql = "SELECT * FROM tWhiteBoardHotList WHERE Type='" & ItemType & "' ORDER BY PartNumber"
sqlComm = New OdbcCommand(sql, sqlConn)
r = sqlComm.ExecuteReader
While r.Read
ControlObject = New HotListItem
ControlObject.Location = New System.Drawing.Point(vpos, hpos + DynLabel.Height)
Tab.Controls.Add(ControlObject)
DynHotListItem = ControlObject
DynHotListItem.lblPartNumber.Text = r!PartNumber
'BUNCH OF CODE HERE TO FILL THE CONTROLS ON HotListItem
ControlCollection.Add(DynHotListItem)
End While
r.Close()
End Sub
Original Code : Sub ClearHotLists()
Dim DynHotListItem As HotListItem
Dim DynLabel As Label
For Each DynTabPage As TabPage In Me.tcMain.Controls
If DynTabPage.Name = "tabShipping" Or DynTabPage.Name = "tabInspection" Or DynTabPage.Name = "tabDeburring" Then
For Each ctr As Control In DynTabPage.Controls
If TypeOf ctr Is HotListItem Then
DynHotListItem = ctr
DynHotListItem.Dispose()
DynHotListItem = Nothing
DynTabPage.Controls.Remove(DynHotListItem)
ctr.Dispose()
Else
DynLabel = ctr
DynLabel.Dispose()
DynLabel = Nothing
DynTabPage.Controls.Remove(DynLabel)
ctr.Dispose()
End If
Next
DynTabPage.Controls.Clear()
End If
Next
System.GC.Collect(GCCollectionMode.Forced)
System.GC.Collect(0, GCCollectionMode.Forced)
System.GC.Collect(1, GCCollectionMode.Forced)
System.GC.Collect(2, GCCollectionMode.Forced)
End Sub
Expected result is for the controls to be disposed, and avoid crashes because of memory leaks.