C#多線程技術(二)

來源:互聯網
上載者:User

上一篇中講述了簡單的C#多線程程式編寫,應該說並不具備太多的痛點,這個程式中,我們將編寫一個比較特殊的線程,兩個線程需要操作同一個List<int>對象:

 

代碼 1  class ThreadCollection{
 2         List<int> elements = new List<int>();
 3         public ThreadCollection(){
 4             elements.Add(10);
 5             elements.Add(20);
 6         }
 7     
 8         public void Run()
 9         {
10             Thread.Sleep(1000);
11             foreach( int item in elements){
12                 Console.WriteLine("Item (" + item + " ) ");
13                 Thread.Sleep(1000);
14             }
15 
16         }
17 
18         public void Add()
19         {
20             Thread.Sleep(1500);
21             elements.Add(30);
22         }
23 
24     }
25 
26 
27     ThreadCollection coll = new ThreadCollection();
28     Thread thread3 = new Thread(
29                new ThreadStart(coll.Run)
30             );
31     Thread thread4 = new Thread(
32                new ThreadStart(coll.Add)
33     );
34 
35     thread3.Start();
36     thread4.Start();
37 

 

 這個時候,系統會拋出一個InvalidOperationException的異常。顯然,我們需要修改程式,一種方法是擷取elments的一個鏡像(snapshot),對鏡像(snapshot)進行操作,這個時候,資料內容被擷取出來,用到的類為:

System.Collections.ObjectModel.ReadOnlyCollection。將原先的foreach語句修改為:

foreach(int item in new ReadOnlyCollection<int>(elements)){...} 

 

這種方法是對elements中的元素進行標記,elements中不允許插入資料,因此系統仍舊會爆出錯誤。徹底的解決方案是使用lock鎖塊語句,使用lock將需要進行鎖的變數傳遞進來,然後用{}操作需要lock的語句。範例程式碼如下:

 

代碼 1     lock(elements){
 2         foreach (int item in elements)
 3         {
 4             Console.WriteLine("Item (" + item + " ) ");
 5             Thread.Sleep(1000);
 6         }
 7     }
 8 
 9 ///////////////////////////////////////////////////////////
10 
11     lock(elements)
12     {
13         elements.Add(30);
14     }

 

 此外,將elements資料拷貝出來,然後對拷貝出來的資料進行遍曆,這個時候,由於寫入和讀資料是兩個完全不同的對象,不存在同步問題,因此,也可以很好運行:

 

代碼1             int[] items;
2             lock(elements){
3                  items = elements.ToArray();
4            }
5             foreach (int item in items)
6             {
7                 Console.WriteLine("Item (" + item + " ) ");
8                 Thread.Sleep(1000);
9             }

 

 

顯然,這種方法,在資料量較大的情況i下,拷貝的時候需要花費較長的時間,並且需要佔據更多的記憶體。但這種方法容易維護與理解。有時候,這種方法也非常有效,因為拷貝的時候,可能還沒有寫入較多的資料,資料仍舊在後台進行寫入,但前台已經可以對部分這些資料進行操作,而不會明顯影響後台操作資料。

 

 

 

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.