2

I have one form that opens another form upon clicking a button. When the new form opens, I have a progress bar complete via a loop, then I want the form to close. Here is the button click event that launches the new form.

    private void calculateButton_Click(object sender, EventArgs e)
    {

        if (checkFormComplete())
        {
            ProgressForm proForm = new ProgressForm();
            proForm.Show();
        }

    }

And here is the code for the new form that completes a progress bar that should then close itself.

    public ProgressForm()
    {
        InitializeComponent();
        for (int i = 0; i < 101; i++)
            calculationProgress.Value = i;

        this.Close();
    }

However, upon running this I get:

Cannot access a disposed object. Object name: 'ProgressForm'.

And the debugger points to this line of my main form:

proForm.Show();

I'm not sure I understand why, or what the proper way to do this is. How is that line being called after the close statement inside my new form?

Anonymous
  • 6,181
  • 7
  • 45
  • 72
  • It looks a lot like you are calling Close() from the ProgressForm constructor, so calling Show() [from calculateButton_Click] after you called Close (which will call Dispose) won't work – Adam Straughan Aug 08 '12 at 16:03

3 Answers3

9

The form is trying to close itself before it's even shown (because you have your code in the constructor). Put your progress bar code and Close() call in the FormLoad or FormShown event instead. Example:

private void ProgressForm_Shown(object sender, EventArgs e)
{
    for (int i = 0; i < 101; i++)
    {
        calculationProgress.Value = i;
        Application.DoEvents(); // force the form to update itself
    }

    this.Close();
}
Hoff
  • 1,762
  • 14
  • 27
  • If you use *Application.DoEvents*, bue *sure* you know how it works http://stackoverflow.com/a/5183623/141172. They generally **don't** behave as you would want. – Eric J. Aug 08 '12 at 16:09
  • Hmmm... but then the changes to *calculationProgress* will not show because the WM_PAINT events are notprocessed. – Eric J. Aug 08 '12 at 16:31
  • Lol chances are he's not going to see anything anyway with a loop that is only incrementing a value. Anyway - added it back in, thanks for the link to the other question. – Hoff Aug 08 '12 at 16:42
2

Allow the loading to complete before you try to close the form :-)

You should start your progress bar loop in the Form_Load event.

However note that looping like that will cause your form to lock up until the progress bar completes rendering.

Do the progress loop in a background thread. A BackgroundWorker is ideal for running the progress loop.

public proForm()
{
    InitializeComponent();
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.WorkerSupportsCancellation = true;
}

proForm_Load()
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

    (int i = 0; i < 101; i++) worker.ReportProgress(i);
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
        resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    this.Close();
}
Eric J.
  • 147,927
  • 63
  • 340
  • 553
0

A constructor is used to initialize an object not destroying the object in the contructor itself.

So a constructor should contain intialization code.

Your code is trying destroy the object with the this.Close(); in the constructor hence the error.

Put your code in Load event of Form.

Change the calculationProgress.Value through a BackgroundWorker's ProgressChanged event

Anirudha
  • 32,393
  • 7
  • 68
  • 89