我开始使用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>
我认为问题是因为我从另一个线程添加了条目,但我不知道如何解决它。
有人可以帮助我吗?
谢谢!
答案 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。