2013-08-02 81 views
2

在這裏,我正在做一個檢查用戶名的過程。我從文本文件創建了一個datagridview並加載了數據。所以datagridview包含前兩列用戶的名字和姓氏。我需要做的是逐行讀取這些值,並發現第一個和最後一個沒有相同的名稱。這些操作在單獨的類中執行。所以我需要從該類中獲取結果並將結果顯示給gridview。當我只使用一個線程時,它一切正常。但是當我使用多個線程時,它只是拋出一個異常,在gridview閱讀中出現異常。這裏是我的編碼:Datagridview C多線程#

static int i, j=0, l=0,k=0,m=0; 

public void check() 
{ 
    for (i = 0; i < dataGridView1.Rows.Count ; i++) 
    { 
     if (InvokeRequired) 
     { 
      Invoke(new UpdateDelegate(delegate 
       { 
        if (i == 0 && j==0) 
        { 
         DataGridViewColumn col = new DataGridViewTextBoxColumn(); 
         col.HeaderText = "Status"; 
         int colIndex = dataGridView1.Columns.Add(col); 
         dataGridView1.Rows[i].Cells[colIndex].Value = "Process Started"; 
         j = 1; 
        } 
        else 
        { 
         dataGridView1.Rows[i].Cells[3].Value = "process Started";    
        } 
       })); 
     } 

     if (InvokeRequired) 
     { 
      Invoke(new UpdateDelegate(delegate 
       { 
        Process obj_reg = new Process(dataGridView1.Rows[i].Cells[1].Value.ToString(),dataGridView1.Rows[i].Cells[2].Value.ToString()); 
        string res = obj_reg.register(); 
        Thread.Sleep(500); 
        if (res.Contains("success")) 
        { 
         if (i == 0 && k==0) 
         { 
          DataGridViewColumn col = new DataGridViewTextBoxColumn(); 
          col.HeaderText = "Result"; 
          int colIndex = dataGridView1.Columns.Add(col); 
          dataGridView1.Rows[i].Cells[colIndex].Value = "Ya its different"; 
          dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Green; 
          k = 1; 
         } 
         else 
         { 
          dataGridView1.Rows[i].Cells[4].Value = "Ya its different";        
          dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Green; 
         } 
        } 
        else 
        { 
         if (i == 0 && m == 0) 
         { 
          DataGridViewColumn col = new DataGridViewTextBoxColumn(); 
          col.HeaderText = "Result"; 
          int colIndex = dataGridView1.Columns.Add(col); 
          dataGridView1.Rows[i].Cells[colIndex].Value = "No its same"; 
          dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red; 
          m = 1; 
         } 
         else 
         { 
          dataGridView1.Rows[i].Cells[4].Value = "No its same"; 
          dataGridView1.Rows[i].DefaultCellStyle.BackColor = Color.Red; 

         } 
        } 
       })); 
     } 
    } 
} 

public void Button1_Click(Object sender, EventArgs e) 
{ 
    Thread[] threads = new Thread[3]; 
    for (int l = 0; l < 3; l++) 
    { 
     threads[l] = new Thread(new ThreadStart(check)); 
    } 
    foreach (Thread t in threads) 
    { 
     t.Start(); 
    } 
} 

請建議我如何使用多線程在這裏...它只是一個例子..請說明任何其他方式..

+0

我爲您格式化了您的代碼。這很痛苦。將來確保代碼可讀。 –

回答

0
  1. 使用lock聲明,以防止不同線程同時運行相同的代碼。您需要一個引用來用作鎖的標識符。這是共同創建一個僅用於鎖定一個簡單的對象:

    static object sync = new Object(); 
    lock (sync) 
    { 
        // do multithreaded stuff here 
    } 
    
  2. UI不是多線程友好的,所以它不是明智的做法是直接更新DataGridView因爲當正在編輯的值刷新。更改DataSource,並在所有線程完成工作時調用Update

    DataSet dataset = dataGridView1.DataSource; 
    
    // do threaded operations on dataset 
    
    // update the datagrid when threads finish work 
    dataGridView1.DataSource = dataset; 
    dataGridView1.Update(); 
    
  3. 我在你的代碼運行發現的相同的代碼3次,而不是分裂您的數據轉換成3個部分,並獨立進行更新。試着做這樣的事情:

    threads[l] = new Thread(new ThreadStart(()=>check(startPosition, endPosition)); 
    

你可以使用BackgroundThread在這裏看到了不同的方法:

Nonblocking update to a DataGridView

+0

當然我可以使用鎖定方法。但是沒有使用多線程。因爲如果我們在當時使用鎖定方式,一個線程只能執行該過程..它也會使得時間過長 – yasmuru

2

有幾個問題與此代碼。

  1. 您正在從工作線程訪問DataGridView。第check代碼的第一行顯而易見。你根本無法做到這一點。

  2. 您定義的變量ijl,想必km(雖然我不認爲他們會在任何地方申報)作爲靜態的。結果是每個工作者線程將使用相同的值並踩在彼此的腳趾上。這對於i來說是一個更大的問題,因爲它實際上是從工作者線程訪問的。其他人可以通過匿名代理進行訪問,該代理將被編組到UI線程中。不過,這可能會造成很多混亂,因爲匿名代表的執行順序是不可預知的。

  3. 您正在從工作線程調用Invoke。這本身不是問題。但是,考慮到你正在將所有有用的工作都回收到UI線程中,這是毫無意義的。想想看。你完成所有的工作來使用一個工作線程,然後你將所有的東西都回傳到UI線程上。你現在有一個比你沒有使用任何工作線程更糟糕的解決方案。

  4. 這真的不是問題,但更多的是我有一個抱怨。爲什麼要打電話InvokeRequired?您已經知道「調用」是必需的,因爲您在開發時知道這些東西位於工作線程上。

我的建議如下。

  1. 根本不使用線程。在這種情況下毫無意義。在另一個線程上可以執行的唯一有用的工作是比較第一個和最後一個名字。這是微不足道的,可以在UI線程上儘快完成。

  2. 如果你真的想用一個單獨的線程,那麼你到UI線程上讀取來自DataGridView值並把它們放在一個單獨的數據結構;一個可以安全地從另一個線程使用。最好是保持這種數據結構與DataGridView一致,當啓動長時間運行操作時,您不需要讀取網格,因爲您已經將數據複製到這個單獨的數據結構中。

+0

感謝您的回覆......但是如果我使用數據結構的方式,當我更新狀態時,問題會再次出現datagridview的。我只是想知道,如果一個線程使它完美,那麼爲什麼不能多線程。應該有一些解決方案,我正在考慮這一點.... – yasmuru

+0

@kavithai_kannan:這是因爲'我'是在線程之間共享,他們都讀取和寫入它沒有任何同步機制。這就是爲什麼你得到'IndexOutOfBoundsException'。 –