I think I finally figured it out.
The logic in my code had 2 steps - call the function that returns SqlDataReader and then use that reader in another function to fill the list:
Dim oReader as SqlDataReader = GetTheReader()
FillTheList(oReader)
Function GetTheReader() looked something like this:
Function GetTheReader() as SqlDataReader
Dim oConn As New SqlConnection("Connection String") : oConn.Open()
Dim oComm As New SqlCommand("Stored Procedure", oConn)
Dim oReader As SqlDataReader = oComm.ExecuteReader(CommandBehavior.CloseConnection)
Return oReader
End Function
It opened connection as a local variable which went out of scope when the function returned back to the caller. And when Generic List was being populated, after another Capacity allocation Garbage Collection claimed that memory by destroying outdated variables (and closing that connection). I was left with a SqlDataReader without a valid connection.
My current solution is to create connection outside GetTheReader
function and pass it as one of the parameters.