2013-01-01 35 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

相關問題