3

I have a Windows Form application that involves two Forms. The child form is used to export data into CSV files, and uses a background worker to write the file. While this is occurring I have the form hidden. The parent form is still active while the background worker is running, so the user can exit the application, even when the background worker is writing files. On the parent form I have added a FormClosing event handler to prompt the user if a background worker is still running. The problem I am encountering is accessing the background worker in the parent form. Here is what I tried...

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        ExportForm eForm = new ExportForm(GridView, TableName, GridProgressBar, ProgressLabel);

        if (eForm.PartWorker.IsBusy == true)
            MessageBox.Show("Busy");
    }

The problem will this is that it is creating a new instance of the Child Form, so the background worker will never have true for it's IsBusy attribute. How could I access this background worker in my parent form so I can check to see if this condition is true.

Here is the code for the PartWorker BackgroundWorker...

    #region PartWorker Events

    void PartWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        GetSwitch();
        int batchNum = 0;
        bool done = false;
        ProgressLabel.Visible = true;

        while (!done)
        {
            for (int i = 1; i <= 100; i++)
            {
                Thread.Sleep(100);
                PartWorker.ReportProgress(i);
            }

            done = Export.ExportPartition(SaveFile, DataTable, 50000, batchNum++);
        }
    }

    void PartWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Progress.Style = ProgressBarStyle.Blocks;
        Progress.Value = e.ProgressPercentage;
        //May want to put the file name that is being written here.
        ProgressLabel.Text = "Writing File: " + e.ProgressPercentage.ToString()  +"% Complete";
    }

    void PartWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Progress.Value = 100;
        ProgressLabel.Visible = false;
        Progress.Visible = false;
        MessageBox.Show("Files sucessfully created!", "Files Saved", MessageBoxButtons.OK, MessageBoxIcon.Information);
        PartWorker.Dispose();
        this.Close();
    }
    #endregion
Andrew
  • 815
  • 2
  • 13
  • 33

2 Answers2

3

Hold a reference to the child form in the main form:

class MainForm : Form {
    private ExportForm exportForm;

    // assign exportForm wherever the child form is created
}

Next, in your ExportForm, create a property that indicates that the form is still busy.
This is a better approach than accessing its BackgroundWorker (read: encapsulation).

class ExportForm : Form {
    public bool IsBusy {
        get { return this.PartWorker.IsBusy; }
    }
}

Then do the check in the main form by accessing the newly created property:

void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.exportForm.IsBusy)
        MessageBox.Show("Busy");
}
Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • I have implemented this and I can see how it works. However, when I set a breakpoint at the MainForm_FormClosing event, it goes to the PartWorker_ProgressChanged event in the ExportForm and iterates through that event handler. When this happens it never executes the MessageBox.Show("Busy") method. – Andrew Aug 09 '11 at 19:00
  • I don't quite understand what you're saying. When does it go into `ProgressChanged` handler? What happens if you don't set the breakpoint? – Dan Abramov Aug 09 '11 at 19:06
  • Yes, it goes to the progress changed handler. If I don't set the breakpoint the MessageBox never shows and you cannot exit the application. I will post the code of my event handlers for the BackgroundWorker. I'm pretty sure the problem lies in there. – Andrew Aug 09 '11 at 19:07
  • 1
    Btw, take a look at [this thread](http://stackoverflow.com/questions/1731384/how-to-stop-backgroundworker-on-forms-closing-event). – Dan Abramov Aug 09 '11 at 19:09
0

Create a singleton business object which holds the background worker, or a collection of background workers (if you may have multiple). Create your background worker from the child form into this singleton and it will be accessible to all in the app domain.

Jay
  • 6,224
  • 4
  • 20
  • 23