为什么我的多线程代码填充网格有时会失败
本文关键字:失败 网格 填充 我的 多线程 代码 为什么 | 更新日期: 2023-09-27 17:50:22
我阅读了关于线程池的文档,并编写了测试代码,将数据从不同的线程加载到两个网格中。但是,有时只有一个网格被填满,而另一个网格仍然是空的。有时候一切都很好。为什么?当我使用waitall时,我得到这个异常:不支持STA线程上的多个句柄的waitall。
private void button1_Click(object sender, EventArgs e)
{
ManualResetEvent[] mre = new ManualResetEvent[2];
mre[0] = new ManualResetEvent(false);
multhread ml = new multhread(mre[0]);
ThreadPool.QueueUserWorkItem(ml.setdatabase,1);
mre[1] = new ManualResetEvent(false);
// multhread ml2 = new multhread(mre[1]);
ThreadPool.QueueUserWorkItem(ml.setdatabase2, 2);
WaitHandle.WaitAll(mre);
dataGridView1.DataSource = ml.propdt;
dataGridView2.DataSource = ml.propdt2;
}
public DataTable propdt2 { get; set; }
public void s()
{
string constring = "DATA SOURCE=.; database=test;integrated security= true; USER ID=sa;password=123456789";
SqlCommand com = new SqlCommand();
SqlConnection con = new SqlConnection(constring);
com.Connection = con;
com.CommandText = " select * from imgtable";
SqlDataAdapter adapt = new SqlDataAdapter(com);
DataTable dt2 = new DataTable();
adapt.Fill(dt2);
propdt2 = dt2;
}
}
public class multhread
{
private ManualResetEvent _doneEvent;
public multhread(ManualResetEvent doevent)
{
_doneEvent = doevent;
}
public static DataTable dt;
public static DataTable dt2;
public DataTable propdt { get; set; }
public DataTable propdt2 { get; set; }
public void setdatabase(Object threadContext)
{
string constring = "DATA SOURCE=.; database=test;integrated security= true; USER ID=sa;password=123456789";
SqlCommand com = new SqlCommand();
SqlConnection con = new SqlConnection(constring);
com.Connection = con;
com.CommandText = " select * from imgtable";
SqlDataAdapter adapt = new SqlDataAdapter(com);
dt2 = new DataTable();
adapt.Fill(dt2);
propdt2 = dt2;
_doneEvent.Set();
// return dt2;
}
public void setdatabase2(Object threadContext)
{
string constring = "DATA SOURCE=.; database=test;integrated security= true; USER ID=sa;password=123456789";
SqlCommand com = new SqlCommand();
SqlConnection con = new SqlConnection(constring);
com.Connection = con;
com.CommandText = " select * from imgtable order by id desc ";
SqlDataAdapter adapt = new SqlDataAdapter(com);
dt = new DataTable();
adapt.Fill(dt);
propdt = dt;
_doneEvent.Set();
}
WaitAll
list在标记为[STAThread]
的线程中是不允许的,这是WinForms应用程序中主线程的情况。我建议不要使用WaitHandle
,而是可以通过调用通知主线程。像这样声明函数:
void dataready
{
dataGridView1.DataSource = ...
}
,而不是在工作线程结束时设置事件,调用这个函数:
Invoke(new Action(dataready));
UI控件是在单线程公寓(STAThread)的线程上创建的。
原因是Windows应用程序使用[STAThread]属性进行属性化。
点击这里阅读更多
http://blogs.msdn.com/b/johnlee/archive/2007/07/10/waithandle-waitall-for-multiple-handles-on-a-sta-thread-is-not-supported.aspx你可以试试
foreach(var a in mre)
{
a.WaitOne();
}
我还没有测试,但我认为它应该有效。
为什么你的代码失败:
你已经从执行Button click事件的线程启动了两个线程池线程。但是当您需要更新从这些线程接收到UI的数据时,您应该使用Invoke来更新UI中的数据。如果不使用Invoke来更新UI上的数据,就会得到Invalid cross thread access error。
要从另一个线程更新UI,请阅读这里的答案
https://stackoverflow.com/a/661706/448407