Question

Ok, in my app there are times when loading the DataGridView can take a minute or two. What I want to do is show a GIF in a form with no border until it reaches the end of the loading function. However, if I do:

Views.Loading ldw = new Views.Loading();
ldw.Show();
...
ldw.Close();

...it never actually draws it to the screen and I can't see it. If I do ShowDialog(), it shows the window but never gets past that line of code. I have a feeling it's because it's not a background worker or because the focus gets set back to the parent because of processing...I don't know.

My form is a blank form, added a picture box, added a gif to the picture box, and made FormBorderStyle = none. Any and all help is appreciated.

Update: Current (non-working) Code

        private void InitializeBackgroundWorker()
        {
            //Defines the DoWork Event Handler for _backgroundWorker.
            _bgWorkerReports.DoWork += new DoWorkEventHandler(bgWorkerReports_DoWork);
            //Defines the RunWorkCompleted Event Handler for _backgroundWorker.
            _bgWorkerReports.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkerReports_RunWorkerCompleted);
        }

        private void bgWorkerReports_DoWork(object sender, DoWorkEventArgs e)
        {
            ldw.Show();
            try
            {                   
                string strFilter = "";

                if (!_strSearchFilter.Equals(""))
                {
                    strFilter += strFilter.Equals("") ? " " + _strSearchFilter : "  and " + _strSearchFilter;
                }

                if (tvFigure.Nodes.Count > 0)
                {
                    if (_strFigureFilter == "ALL")
                    {
                        strFilter += " " + Constants.GetColumnName("Figure") + " LIKE '%%' ";
                    }
                    else if (!_strFigureFilter.Equals("") && !_strFigureFilter.Equals(tvFigure.TopNode.Name))
                    {
                        if (_strSearchFilter.Equals("") || !cbCurrentFigure.Checked)
                        {
                            strFilter += strFilter.Equals("") ? " " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'" : " and " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'";
                        }
                    }
                }

                if (!_strIndentureFilter.Equals(""))
                {
                    strFilter += strFilter.Equals("") ? " " + _strIndentureFilter : "  and " + _strIndentureFilter;
                }

                if (!_strReportFilter.Equals(""))
                {
                    strFilter += (!strFilter.Equals("") ? " and" : "") + " part_id in (" + _strReportFilter + ")";
                }

                if (strFilter.Length > 0)
                {
                    BindingSource bSource = new BindingSource();
                    bSource.DataSource = _dataController.PopulateDataGrid(_nViewMode, strFilter).Tables[0];

                    //Set DataSource to bindingSource for DataGridView.
                    if (_lstValidationResults.Count > 0)
                    {
                        dgvParts.DataSource = _lstValidationResults;
                        foreach (DataGridViewColumn dc in dgvParts.Columns)
                        {
                            dc.DataPropertyName = "ErrorMessage";
                            dc.Visible = true;
                            dc.SortMode = DataGridViewColumnSortMode.Programmatic;
                            dc.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
                        }
                        dgvParts.AutoResizeColumns();
                        return;
                    }
                    else if (!string.IsNullOrEmpty(_strFigureFilter))
                    {
                        dgvParts.DataSource = bSource;
                        dgvParts.Columns[0].Visible = false;
                        dgvParts.Columns["Description"].Resizable = DataGridViewTriState.False;
                        dgvParts.Columns["Description"].Width = 750;
                    }

                    // Automatically resize the visible rows.
                    foreach (DataGridViewColumn col in dgvParts.Columns)
                    {
                        col.SortMode = DataGridViewColumnSortMode.Automatic;
                        if (col.Name != "Description")
                        {
                            dgvParts.AutoResizeColumn(col.Index);
                        }
                    }
                    dgvParts.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;

                    // Hide the ToolTips for all the cells - redisplay if there is a report.
                    dgvParts.ShowCellToolTips = true;

                    // Set the dataGridView control's border.
                    dgvParts.BorderStyle = BorderStyle.Fixed3D;

                    // Get and set the ipb_number to the label.
                    string ipb_number = _dataController.IPBNumber;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void bgWorkerReports_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ldw.Close();
            this.Cursor = Cursors.Default; //Throws error (Cross-thread)

            FormatCells();
            BuildColumnsComboBox();

            int nTotalCount = 0;

            foreach (ListViewItem lvi in listView1.Items)
            {
                int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
                nTotalCount += nCount;
                lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text.Trim() + " (") + nCount.ToString() + ")";
            }

            rbAllReports.Text = (rbAllReports.Text.Contains("(") ? rbAllReports.Text.Substring(0, rbAllReports.Text.IndexOf("(") + 1) : rbAllReports.Text + " (") + nTotalCount.ToString() + ")";
            int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
            rbTaggedRecords.Text = (rbTaggedRecords.Text.Contains("(") ? rbTaggedRecords.Text.Substring(0, rbTaggedRecords.Text.IndexOf("(") + 1) : rbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";
        }
Was it helpful?

Solution

Ideally you would have two threads: the GUI thread and the working thread (which can be a BackgroundWorker). Create and show the window in the GUI thread. Handle the loading in the BackgroundWorker's DoWork event. When the loading is done you can call Close() on the load window from the RunWorkerCompleted event and dispose of it.

LoadWindow loadWindow = new LoadWindow();
loadWindow.TopMost = true;  // make sure it doesn't get created behind other forms
loadWindow.Show();

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // do your loading here
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // set DataGridView datasource here
    ...

    // close loading window
    loadWindow.Close();
}

The problem you might have with displaying the window could be from the TopMost property, which must be set to true. You can also try calling BringToFront() on the loading window after you've created and shown it.

OTHER TIPS

Yes, BackgroundWorker is for exactly this type of purpose. A couple things to add:

  1. Do not interact with the UI in the worker_DoWork event as it is running on a background thread. Set e.Result when you're finished, which you can check from the RunWorkerCompleted event - or use a form-level variable.
  2. Let any exceptions fall through in the worker_DoWork event and you will see them in the worker_RunWorkerCompleted event in e.Error.
  3. If you need the ability to cancel your load, set worker.WorkerSupportsCancellation and check the e.Cancel while in your DoWork event, then you can check e.Cancelled in your RunWorkerCompleted event.
  4. You should call .Dispose() on your BackgroundWorker when finished.

You'll have to run the code to fill the grid on another thread. Something like:

// Set the picturebox loading state, resize the form etc.
PictureBox.SetLoadingImage();

// Initialize a new thread
Thread t = new Thread(new ThreadStart(() =>
{
    // Fill the gridview here
    GridView1.DataSource = FillWithData();
    GridView1.DataBind();

    // When finished, reset the picturebox on it's own thread
    PictureBox.Invoke((MethodInvoker)(()=> PictureBox.ClearLoadingImage() ));
}));

// Run the thread.
t.Start();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top