views:

340

answers:

1

I cannot get to the bottom of this error because it happens only in one instance, and I can't find any code that can be the cause of the error.

I have a 3.5 web service that I'm calling from a multi-threaded, CAB client. I have a bunch of unit tests against the web service (from both 3.5 and 2.0 code), and it works fine. However, in the actual application, it doesn't work 90% of the time and, the remaining 10% of the time, it decides to work.

The code:

Friend Function ExecuteSearch(ByVal query As String) As List(Of SomeObject)
    Dim searchResults As List(of Object) = _searcher.UserSearch(query)
    Return searchResults
End Function 

// In Searcher
Public Function UserSearch(ByVal query As String) As List(Of SomeObject)
    Return Translate(Search.GetResults(query))
End Function

// In Search
Public Function GetResults(ByVal query As String) As List(Of SomeObject)
    Dim service As New FinderService.FinderService()
    Dim results As New List(Of String)
    Dim serviceResults As IEnumerable(Of String) = service.Search(query)    // <-- ERRORS OUT HERE 

    results.AddRange(serviceResults)

    Return results
End Function

// In the service
Public Function Search(ByVal query As String) As IEnumerable(Of String)
        Initialize() // Initializes the _accounts variable
        Dim results As New List(of String)
        For Each account As User In _accounts
            If a bunch of conditions Then
                results.Add(account.Name)
            End IF 
        End For 

        Return results 
End Function 

The breakpoints hit these codes (in this order). The line that errors out is in the "GetResults" method.

Any help would be appreciated.

+4  A: 

Ah, the Heisenbugs :D

Apparently _accounts get modified during the loop. You can alleviate it by doing

For Each account As User In _accounts.ToList()

so a copy of current _accounts is created and enumerated and not the actual collection that might change

+1 for most likely answer with the information provided.
Greg D
+1 I agree given the information.
Hogan
_accounts is too large to be copied. Since I posted this question, I added a lock on the *only* location where _accounts gets updated, but that didn't make a difference.public sub Initialize SyncLock _accounts _accounts.AddRange(get accounts from db) End SyncLock end sub
Sadhana
You realise you only copy references, not the whole contents So unless you have say half a billion accounts it won't be a problem? Nevertheless, if you want to add a lock, you have to to SyncLock ForEach loop either.
@wwosik -- not half a billion; just a couple of million. :-) I will go with the ToList.
Sadhana