c#winform程序,datagridview的数据源来自一个DataTable,但获取DataTable需要一定的时间,使用单线程的话,获取得DataTable后再显示到datagridview,会大大的降低用户体验。现在考虑使用多线程,用一个线程T1去获取DataTable,主线程sleep 1秒左右,再去读取DataTable,DataTable由T1动态更新。求大神解惑,这种方法可行吗?如果可行,如何实现?有例子更好。非常感谢。
调试欢乐多
sleep使得线程挂起,如果是主线程挂起,那么程序就假死了。
多线程更新用户界面的例子可以看这里
http://blog.csdn.net/niewq/article/details/5607821
ThreadPool.QueueUserWorkItem(p =>
{
DataTable dtbl = new DataTable();
// 读 dtbl
// 读完后下面的代码给 dataGridView1 赋值
this.Invoke((MethodInvoker)(() => dataGridView1.DataSource = dtbl));
});
public delegate void GetData();
private void BindData()
{
if (dataGridView1.InvokeRequired) //如果是线程中访问的
{
this.BeginInvoke(new GetData(BindData));
return;
}
dataGridView1.DataSource = ds.Tables["stuff"];
}
private void Foo()
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data source=c:\\txl.mdb");
con.Open();
string sql = "select * from stuff";
OleDbDataAdapter da = new OleDbDataAdapter(sql, con);
ds = new DataSet();
da.Fill(ds, "stuff");//填充到ds
BindData();//执行绑定
}
private void button8_Click(object sender, EventArgs e)
{
//创建线程,并执行Foo
Thread th = new Thread(new ThreadStart(Foo));
th.Start();
}
不是有BeginXXXX之类的异步方法吗
--需要注意 UI元素 需要在主线程才能操作,DataTable查询完成后需要调用Form上的Invoke函数,切换线程。
然后可能还需要让控件成为锁定状态,避免乱点,导致你逻辑出问题。然后开启线程
执行读取数据
将数据赋值给DATATABLE的方法写在新开启的线程里就行了
然后就完事了。。
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
e.Value = DataTable.Rows[e.RowIndex][e.ColumnIndex];
}
虚模式下我不知道如何动态更新datagridview的显示了。它没法直接增加行
DataTable TableData;
private void Detail_Load(object sender, EventArgs e)
{
Thread ReplayFlightData;
ThreadStart StartReplayFlightData = new ThreadStart(getTableData);
ReplayFlightData = new Thread(StartReplayFlightData);
ReplayFlightData.Start(); Thread.Sleep(1000);
//sleep1秒后,调试发现TableData的行数仍然为0?
if (TableData.Rows.Count == 0)
{
Thread.Sleep(1000);
}
else
{
int c_intColumnCount = TableData.Columns.Count;
int Column_Width = 60000 / (c_intColumnCount); //datagridview的最大宽度为65535,但考虑到留出一定的裕度,设为60000
for (int i = 0; i < c_intColumnCount; i++)
{
if (c_intColumnCount > 500)
{
DataGridViewColumn l_dgvClmn = new DataGridViewTextBoxColumn();
//l_dgvClmn.Width = 2;
l_dgvClmn.Name = TableData.Columns[i].ColumnName;
l_dgvClmn.HeaderText = TableData.Columns[i].Caption;
try
{
dataGridView1.Columns.Add(l_dgvClmn);
dataGridView1.Columns[i].FillWeight = Column_Width;
//dataGridView1.Columns[i].Width = 2;
}
catch (Exception)
{
MessageBox.Show("显示参数太多,表格显示宽度不能超过65535像素,部分未能显示。");
break;
}
}
else
{
DataGridViewColumn l_dgvClmn = new DataGridViewTextBoxColumn();
l_dgvClmn.Name = TableData.Columns[i].ColumnName;
l_dgvClmn.HeaderText = TableData.Columns[i].Caption;
dataGridView1.Columns.Add(l_dgvClmn);
}
} dataGridView1.VirtualMode = true;
dataGridView1.RowCount = TableData.Rows.Count;
//冻结前三行
dataGridView1.Rows[3].Frozen = true;
}
}
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
e.Value = DataTable.Rows[e.RowIndex][e.ColumnIndex];
}
//获取datatable函数,代码太长,省略,是一行一行获取到datatable的
private void getTableData()
{
//省略
}