1

好的,在我的应用程序中,有时加载 DataGridView 可能需要一两分钟。我想要做的是以没有边框的形式显示一个GIF,直到它到达加载函数的末尾。但是,如果我这样做:

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

...它从来没有真正将它绘制到屏幕上,我看不到它。如果我执行 ShowDialog(),它会显示窗口但永远不会超过那行代码。我有一种感觉,这是因为它不是后台工作人员,或者因为处理过程中焦点又回到了父级……我不知道。

我的表格是空白表格,加了一个图片框,给图片框加了个gif,并且使FormBorderStyle = none。任何和所有的帮助表示赞赏。

更新:当前(非工作)代码

        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() + ")";
        }
4

3 回答 3

9

理想情况下,您将有两个线程:GUI 线程和工作线程(可以是 a BackgroundWorker)。在 GUI 线程中创建并显示窗口。BackgroundWorker处理'DoWork事件中的加载。加载完成后,您可以Close()RunWorkerCompleted事件调用加载窗口并处理它。

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();
}

您在显示窗口时可能遇到的问题可能来自TopMost属性,该属性必须设置为true. 您也可以BringToFront()在创建并显示加载窗口后尝试调用它。

于 2010-09-21T13:21:39.667 回答
1

是的,BackgroundWorker 正是出于这种目的。补充几点:

  1. 不要在 worker_DoWork 事件中与 UI 交互,因为它在后台线程上运行。完成后设置 e.Result,您可以从 RunWorkerCompleted 事件中检查 - 或使用表单级变量。
  2. 让任何异常在worker_DoWork 事件中消失,您将在e.Error 的worker_RunWorkerCompleted 事件中看到它们。
  3. 如果您需要取消负载的能力,请设置 worker.WorkerSupportsCancellation 并在 DoWork 事件中检查 e.Cancel,然后您可以在 RunWorkerCompleted 事件中检查 e.Cancelled。
  4. 完成后,您应该在 BackgroundWorker 上调用 .Dispose()。
于 2010-09-21T13:36:31.847 回答
0

您必须运行代码才能在另一个线程上填充网格。就像是:

// 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();
于 2010-09-21T13:23:27.667 回答