Fog Creek Software
Discussion Board




Welcome! and rules

Joel on Software

Bad bug in .net?

We recently stumbled across a huge bug. I rarely say that the underlying API is at fault but in this case I am going that way.

We have a listbox that shows the topic returns of a search. This list can be from 0 to 3,000 or more items.

To speed the search up I reference the enumerator directly and "blast" the items into the listbox. This works great and prevents the listbox from scrolling as items are entered.

There is a label that displays the number of hits returned. The hits are returned in an ArrayList.

Here is the bug.

On 50% of the machines tested (4 out of 8 with various OS's from windows 98 to Windows 2003
) a search that returns exactly one hit does not dispay the one topic in the listbox. Any other number of hits from 0 to 3k work fine.

At first I had set the label to display the listbox.count value.

This displayed 1, but no item was displayed in the tree.

I set it to display the search results array count. Same thing.

After the search results are displayed, if there is a topic in the listbox, it is selected.  Keep in mind that there are three instances before this code that return from the function early if the search results count is 0.

if(listbox.items.count>0)
{
    listbox.selectedIndex=0;
}

This errors out on the second line with a null reference, just like if you set the listbox index to an index number that is invalid.

What I don't understand is how if the IF statement is true then the second line of code can fail?

I put in a work around where if the search returns 1 item then it is added by the listbox.items.add method instead.

We checked on all machines with a 2 hit query and the issue did not come up, so again it was very specifically 1 hit returns, and only on certain machines.

Jon Kenoyer
Thursday, October 09, 2003

As I expect a common answer to your question is going to be "works fine for me" ;) it would be extremely useful if you can provide a short code example that can reproduce your problem.

Mind you, the chances are if you scope it down that you'll find the cause of this behaviour or prove that it's a geniune bug ;)

Alternatively, a largeish code snippet from your actual application could be useful. In particular, the bit where you actually populate the listbox.

id
Thursday, October 09, 2003

Here is the code snippet where it fills the listbox.

findResults is the ArrayList of returned hits.

Note that the returned class has a toString method that returns a valid string.
                    IDictionaryEnumerator myEnumerator=findResults.GetEnumerator();
                
                    this.Cursor=Cursors.WaitCursor;
                    lstFindResults.BeginUpdate();
                    lstFindResults.Items.Clear();
                    while(myEnumerator.MoveNext())
                    {
                        searchItem searchEntry=(searchItem)myEnumerator.Value;
                        lstFindResults.Items.Add(searchEntry);
                    }
                    lstFindResults.EndUpdate();
                    this.Cursor=Cursors.Default;                
                    trace.Trace("search done");

Jon Kenoyer
Thursday, October 09, 2003

First of all, unless I missed it you haven't specified if this is a Windows.Forms listbox or a Web.UI.Forms listbox. The two are completely different implementations.

In case you're talking about Winforms, there's an obscure bug with BeginUpdate/EndUpdate that causes the ListBox to ignore a *single* item that is added between these statements. Maybe the bug strikes on other occasions, too.

So I'd suggest trying to comment out the BeginUpdate and EndUpdate calls. If the program now works correctly you know at least the reason, although I don't know the cure.

Chris Nahr
Thursday, October 09, 2003

Good point Chris, being in the Windows.Forms enviroment I forget about the Web.UI stuff ;)

On the bug issue, is it documented? Does it still exist in .NET 1.1? As I've tried a simple test and don't seem to be having any problems with single entries between Begin/EndUpdate (in .NET 1.1 on W2K).

Jon, here is my code for it, it's called on a simple form that has a listbox (resultBox) and a button that populates the listbox (winforms) on Click, here is the onClick code:

    ListDictionary findResults = new ListDictionary();
    findResults.Add("Item1", "Value1");

    resultBox.BeginUpdate();
    resultBox.Items.Clear();
    foreach (object searchEntry in findResults.Values)
    {
        resultBox.Items.Add(searchEntry);
    }
    resultBox.EndUpdate();

    this.resultBox.SelectedIndex = 0;

It might worth trying s/th similar in a simple test app and see if you can still have an error.

Also, your enviroment info on Windows.Form vs Web.UI and .Net version would be useful.

Btw I noticed you're not using "foreach" in your snippet. Is there any reason why not? The code is clearer without all this "while (iterator.HasNext())" -type constructs.

It's even going to be (finally!) in JDK 1.5, though imo they chose an obscure syntax - it will be "for (Object o : Collection)".

id
Thursday, October 09, 2003

"there's an obscure bug with BeginUpdate/EndUpdate that causes the ListBox to ignore a *single* item that is added between these statements. Maybe the bug strikes on other occasions, too."

Well there we go.

This is indeed a winform. Sorry should of made that clear.

Thanks guys at least now I know that I wasn't losing my mind.

PS besides being easier to read is there any performance difference between using a while vs foreach statement?  I think this is about the only place in the code I used that.

Jon Kenoyer
Thursday, October 09, 2003

Oh I should mention another symptom of this bug is if you ask the listbox for its item count it returns 1 instead of 0.

Jon Kenoyer
Thursday, October 09, 2003

id: This bug is not documented, and I was unable to create a simple test case to reproduce it. It's one of those infernal bugs that only strike occasionally, but I did have a reproducable occurrence in a fairly complex application.

Jon: So did removing BeginUpdate/EndUpdate fix the problem for you? Just curious if it's indeed the same bug.

As for while vs foreach, the major (potential) difference in performance is between using enumerators vs using indexers. Which one is faster depends on their respective implementation with a particular collection class. Using enumerators with while should perform exactly as foreach, it just won't look as nice.

Chris Nahr
Saturday, October 11, 2003

Removing the begin/end and instead using the typical addItem method did indeed solve the problem.

Unluckily, since in some common cases we are inserting 2-3 thousand items in the list, permantly removing them was not an option.

Instead there is a code fork where, if there is only 1 item to insert, the code uses the typical method.

Bad times :(

Jon Kenoyer
Saturday, October 11, 2003

"This bug is not documented, and I was unable to create a simple test case to reproduce it. It's one of those infernal bugs that only strike occasionally, but I did have a reproducable occurrence in a fairly complex application."

Not to say whether this is true or not, but pretty much every time I uttered that thought, it turned out to be my code that was to blame.

Brad Wilson (dotnetguy.techieswithcats.com)
Saturday, October 11, 2003

Brad, the entire code block consists of four lines, and uncommenting two of those four lines -- the ones that shouldn't have any effect -- makes the ListBox behave incorrectly. I've analyzed this issue for hours because I, too, though that I had made some other mistake. But this particular case was really quite clear.

Chris Nahr
Sunday, October 12, 2003

*  Recent Topics

*  Fog Creek Home