views:

254

answers:

2

Hi,

I am loading the images using the BackgroundThread. I am receving "nullreferenceexception unhandled by user code" after loading all the images into the Listview. What could be the issue? Please let me know.

   private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            int progress = 0;

            string pname;
            Image myImage;
            max_length = files.Length;
            for (int k = 0; k < files.Length; k++)
            {
                ProgressInfo info = new ProgressInfo();
               pname = System.IO.Path.GetFullPath(files[k]);
                myImage = Image.FromFile(pname);
                info.Image = myImage;
                info.ImageIndex = k;
                backgroundWorker1.ReportProgress(progress, info);
                myImage = null;
            }
        }
        catch (Exception ex)
        {
            throw ex.InnerException;
        }
    }

    private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

            try
            {

                //Get image.
                ProgressInfo img = e.UserState as ProgressInfo;
                //Set image to ListView here.
                ImgListView.Images.Add(getThumbnaiImage(ImgListView.ImageSize.Width, img.Image));
                fname = System.IO.Path.GetFileName(files[img.ImageIndex]);
                ListViewItem lvwItem = new ListViewItem(fname, img.ImageIndex);
                lvwItem.Tag = files[img.ImageIndex];

                lstThumbNailView.Items.AddRange(new ListViewItem[] { lvwItem });

                percent = (int)((float)100 * (float)i / (float)files.Length);
                this.progressBar1.Value = (int)percent;
                 this.label1.Text = "Loading images...";

            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
    }
+1  A: 

Judging from your comments, you're seeing the error because not all exceptions have an InnerException. If InnerException is null, you will see this problem.

There are several issues at work here though. First, here is the proper try/catch method:

try
{
  // Code here
}
catch (Exception ex)
{
  // Handle your exception
  throw; // Rethrow the same exception, preserving the stack trace (optional)
}

Second, you are likely abusing the purpose of ReportProgress. You should attempt to do all your logic in your backgroundWorker_DoWork, and send the percentage (between 0 and 100) to ReportProgress to update any progress bars.

You may have used the ReportProgress in the way you did to fix a multi-threaded issue. To add items to a ListBox across threads, wrap your code in an anonymous method using the BeginInvoke function

Example:

// Note: I haven't error checked this, and this is only a rough idea of what 
// you're trying to do. I'm not even sure of the overall goal here.
this.lstThumbnailView.Invoke((Action)delegate
{
  ListViewItem lvwItem = new ListViewItem(name, img.ImageIndex);
  ivwItem.Tag = files[img.ImageIndex];
  lstThumbNailView.Items.Add(lvwItem);
});
Will Eddins
So the answer is not to throw an InnerException. Could you please suggest?
My suggestion is that theres another issue in your code. Remove the try/catch completely and it should show you the real error and where it is happening. Your try/catch is only covering up the real issue here.
Will Eddins
Where do I have to call this anonymous method?
You can only updating GUI elements on the main thread. ReportProgress is called on the main thread, which is why it might work as-is, but that still doesn't make it right.
Will Eddins
What is the proper way to load the images?
Without having a bigger picture of what you're doing and how everything is structured, its hard to say what the proper way is. For now, I'd recommend removing your try-catch blocks so your application can crash at the exact point the exception is handling and you can see what's causing your problems, and concentrate on that.
Will Eddins
If you want to rethrow an exception in a catch block it's best to use "throw" rather than "throw ex" to preserve the original stack trace.
Joe
@Joe: You're correct. I edited my answer to reflect this.
Will Eddins
A: 

Thanks for the quick response. Here are the changes I made. It seems to be working fine.

   private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

            try
            {
                ProgressInfo img = e.UserState as ProgressInfo;
                LoadImages(img);
                this.progressBar1.Value = img.Percent;
                this.label1.Text = "Loading images...";

            }
            catch (Exception ex)
            {
               throw ex;
            }
    }

    private void LoadImages(ProgressInfo img)
    {
        ImgListView.Images.Add(getThumbnaiImage(ImgListView.ImageSize.Width, img.Image));
        this.lstThumbNailView.Invoke((Action)delegate
        {
            fname = System.IO.Path.GetFileName(files[img.ImageIndex]);
            ListViewItem lvwItem = new ListViewItem(fname, img.ImageIndex);
            lvwItem.Tag = files[img.ImageIndex]; 
            lstThumbNailView.Items.Add(lvwItem); 
        });
    }
There's no point to catch the exception and then throw it again. You only lose information from the stack trace by doing so.
Drew Noakes
After removing try catch block I am getting OutofMemory exception. I am loading about 140 thumbnails.
I can't believe that the catch block makes any difference. You are still throwing an exception. The only difference I can see is that the stack trace would be based off your catch block, not the original site at which the exception was raised.
Drew Noakes