2013-01-01 27 views
0

我读了关于线程池的文档,并且我写了测试代码来将数据加载到来自不同线程的两个网格中。但是,有时候,只有一个网格填充,而另一个网格是空的。有时候一切正常。为什么? 当我使用waitall我得到这个异常:不支持WAA线程上的多个句柄的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(); 

    } 
+0

此代码是否在Web应用程序中? – Dinesh

+0

没有它的胜利应用程序。 – heavy

+0

您是否试图理解这个理论,或者这是否意图成为实际的生产代码?虽然可以通过这种方式同时执行SQL Server命令,但绝对不是推荐的方法。你在使用.NET 4.5吗? – RickNZ

回答

1

WaitAll IST标记为[STAThread]这是在一个WinForms应用程序的主线程的情况下更新UI。 我建议不要与WaitHandle一起工作,而是可以通过调用通知主线程。声明这样的函数:

void dataready 
{ 
    dataGridView1.DataSource = ... 
} 

,并在您的工作线程结束设置事件的instad调用此函数:

Invoke(new Action(dataready)); 

这应该做的伎俩。

0

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

我没有测试过,但我认为它应该工作。

为什么你的代码失败:

您已经开始从线程正在执行的按钮点击事件的两个线程池线程。但是,无论何时需要将从这些线程接收的数据更新到UI,都应该使用Invoke来更新UI中的数据。如果未使用Invoke来更新UI上的数据,则会收到无效的跨线程访问错误。

从另一个线程读取的回答在这里线程不允许

https://stackoverflow.com/a/661706/448407

+0

谢谢你的回复,但你的代码没有工作 – heavy

+0

这里指的是WaitAll不会工作,你需要使用它来等待数组中的所有WaitHandles。您提供的代码需要进行改进才能正确同步以正确绑定网格。你使用的是什么版本的框架?在v4或更高版本的情况下,你可能想要使用Task来做到这一点,它可以帮助你使代码看起来很简单 – Dinesh

+0

我使用的是version4 – heavy

相关问题