MessageBox使用Form进度

时间:2016-04-16 13:27:45

标签: c# multithreading winforms

我开始使用C#,我正在尝试创建类似于messageBox的东西,以便在我的应用程序运行时显示进度。我的应用程序从数据库中获取条目并将该数据添加到网格中。

经过大量的搜索,我找到了一种方法,可以在不冻结UI的情况下完成;使用线程:

ProgressDialog progressDialog = new ProgressDialog();

progressDialog.ProgressMax = (int)total;

Thread backgroundThread = new Thread(
    new ThreadStart(() =>
    {
        try
        {
            psp_grid.DataSource = null;
            psp_grid.Rows.Clear();

            progressDialog.Title = "Cargando listado...";
            progressDialog.Status = "Se está cargando el listado de juegos. Por favor espere...";
            progressDialog.Message = "Recuperando juegos de la base de datos";

            using (SQLiteCommand cmd = new SQLiteCommand(query, handle))
            {
                using (SQLiteDataReader rdr = cmd.ExecuteReader())
                {
                    while (rdr.Read())
                    {
                        progressDialog.ProgressActual = Actual;
                        progressDialog.Message = "Añadidos " + Actual + " juegos de " + total;
                        psp_grid.Rows.Add();
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[0].Value = (Int64)rdr["ID"];
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[1].Value = (byte[])rdr["ICON0"];
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[2].Value = "Hola Primo\n" + rdr["ID"].ToString() + (string)rdr["TITLE"];

                        switch (int.Parse(rdr["RATE"].ToString()))
                        {
                            case 1:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._1star;
                                break;

                            case 2:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._2star;
                                break;

                            case 3:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._3star;
                                break;

                            case 4:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._4star;
                                break;

                            case 5:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._5star;
                                break;

                        }

                        if (psp_grid.RowCount > 7 && changed == false)
                        {
                            psp_grid.Columns[2].Width = 434;
                            changed = true;
                        }

                        Actual++;
                    }
                }
            }

            psp_grid.Rows[0].Cells[0].Selected = true;
        }

        catch (Exception ex)
        {
            System.Diagnostics.Debug.Write(ex.ToString());
        }

        if (progressDialog.InvokeRequired)
            progressDialog.BeginInvoke(new Action(() => progressDialog.Close()));
    }));

// Start the background process thread
backgroundThread.Start();

// Open the dialog
progressDialog.ShowDialog();

该代码在最终程序上工作正常,但在调试时,它在第二次运行时失败,我想学习最好的方法,没有错误。

错误是(西班牙文):

Activado    Evento  Hora    Duración    Subproceso
Excepción: Se detectó una excepción: "System.InvalidOperationException" en System.Windows.Forms.dll ("Operación no válida a través de subprocesos: Se tuvo acceso al control '' desde un subproceso distinto a aquel en que lo creó."). Se detectó una excepción: "System.InvalidOperationException" en System.Windows.Forms.dll ("Operación no válida a través de subprocesos: Se tuvo acceso al control '' desde un subproceso distinto a aquel en que lo creó.") 12,02s      [11616] <Sin nombre> 

我认为问题是因为我从另一个线程添加了条目,但我不知道如何解决它。

有人可以帮助我吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

Microsoft explains how to make thread-safe calls.

以下是他们网站上的示例:

private delegate void SetTextCallback(string text);

private void SetText(string text)
{
    if (textBox1.InvokeRequired)
    {   
        SetTextCallback d = new SetTextCallback(SetText);
        Invoke(d, new object[] { text });
    }
    else
    {
        textBox1.Text = text;
    }
}



private void ThreadProcSafe()
{
    SetText("This text was set safely.");
}

答案 1 :(得分:0)

最后工作没有问题。

ProgressDialog progressDialog = new ProgressDialog();

Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
    try
    {
        psp_grid.DataSource = null;
        psp_grid.Rows.Clear();

        progressDialog.ProgressMax = (int)total;
        progressDialog.Title = "Cargando listado...";
        progressDialog.Status = "Se está cargando el listado de juegos. Por favor espere...";
        progressDialog.Message = "Recuperando juegos de la base de datos";

        using (SQLiteCommand cmd = new SQLiteCommand(query, handle))
        {
            using (SQLiteDataReader rdr = cmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                        progressDialog.ProgressActual = Actual;
                        progressDialog.Message = "Añadidos " + Actual + " juegos de " + total;

                    if (psp_grid.InvokeRequired)
                    {
                        //MessageBox.Show("Invocando...");
                        psp_grid.Invoke(new Action(() => psp_grid.Rows.Add()));

                        Int64 _ID = (Int64)rdr["ID"];
                        byte[] _ICON0 = (byte[])rdr["ICON0"];
                        string _Text = "Hola Primo\n" + rdr["ID"].ToString() + (string)rdr["TITLE"];

                        psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[0].Value = _ID));
                        psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[1].Value = _ICON0));
                        psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[2].Value = _Text));

                        switch (int.Parse(rdr["RATE"].ToString()))
                        {
                            case 1:
                                psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._1star));
                                break;

                            case 2:
                                psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._2star));
                                break;

                            case 3:
                                psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._3star));
                                break;

                            case 4:
                                psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._4star));
                                break;

                            case 5:
                                psp_grid.Invoke(new Action(() => psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._5star));
                                break;

                        }

                        if (psp_grid.RowCount > 7 && changed == false)
                        {
                            psp_grid.Invoke(new Action(() => psp_grid.Columns[2].Width = 434));
                            changed = true;
                        }
                    }
                    else
                    {
                        psp_grid.Rows.Add();
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[0].Value = (Int64)rdr["ID"];
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[1].Value = (byte[])rdr["ICON0"];
                        psp_grid.Rows[psp_grid.RowCount - 1].Cells[2].Value = "Hola Primo\n" + rdr["ID"].ToString() + (string)rdr["TITLE"];

                        switch (int.Parse(rdr["RATE"].ToString()))
                        {
                            case 1:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._1star;
                                break;

                            case 2:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._2star;
                                break;

                            case 3:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._3star;
                                break;

                            case 4:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._4star;
                                break;

                            case 5:
                                psp_grid.Rows[psp_grid.RowCount - 1].Cells[3].Value = GameStation_Game_Manager.Properties.Resources._5star;
                                break;

                        }

                        if (psp_grid.RowCount > 7 && changed == false)
                        {
                            psp_grid.Columns[2].Width = 434;
                            changed = true;
                        }
                    }

                    Actual++;
                }
            }
        }

    }

    catch (Exception ex)
    {
        System.Diagnostics.Debug.Write(ex.ToString());
    }

    if (progressDialog.InvokeRequired)
        progressDialog.BeginInvoke(new Action(() => progressDialog.Close()));
}));

有点慢,但即使在调试模式下也能正常工作。

再次感谢ElectroByt。