程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c#中Lock(鎖)的研究以及跨線程UI的操作

c#中Lock(鎖)的研究以及跨線程UI的操作

編輯:C#入門知識

c#中Lock(鎖)的研究以及跨線程UI的操作


本文只針對C#中,多線程同步所用到的鎖(lock)作為研究對象。由於想更直觀的顯示結果,所以,在做demo的時候,就把多線程通過事件操作UI的代碼也寫了出來,留作備忘和分享吧。       其實多線程的同步,使用同步鎖的方法用了好多次,今天無意中看到MSDN中,建議用:   1 private static readonly object locker1 = new object(); 2 private readonly object locker2 = new object(); 備注:原文並沒有加readonly,是我後來自己加進去的。   我不僅思考了一下他們的區別。   然後我寫了一段代碼進行測試,測試類代碼如下:   復制代碼     /// <summary>     /// 跨線程操作UI的時候傳遞的參數,本文為了顯示消息,所以簡單的封裝了一個     /// </summary>     public class MyEventArgs : EventArgs     {         public readonly string Message = string.Empty;         public MyEventArgs(string msg)         {             this.Message = msg;         }     }     /// <summary>     /// 測試類,用於測試2種鎖的區別     /// </summary>     public class LockTest     {         //2個鎖         private static readonly object Locker1 = new object();         private readonly object Locker2 = new object();           /// <summary>         /// 跨線程操作UI的委托和事件         /// </summary>         public delegate void MessageEventHandler(object sender, MyEventArgs e);         public event MessageEventHandler MessageEvent;         public void OnMessage(MyEventArgs e)         {             if (this.MessageEvent != null) MessageEvent(this, e);         }           //要鎖的變量,通過它可以看出2種鎖在不同情況下的效果         private int num = 0;         //實例名字         private readonly string Name;         public LockTest(string name)         {             Name = name;         }         //第一種鎖執行的方法         public void AddNum1()         {             lock (Locker1)             {                 num = 0;                 ShowMessage();             }         }         //第二種鎖執行的方法         public void AddNum2()         {             lock (Locker2)             {                 num = 0;                 ShowMessage();             }         }         //鎖內的一些操作,並通過事件,把關鍵的消息顯示到主線程中的UI裡         private void ShowMessage()         {             string msg = "";             for (int i = 0; i < 10; i++)             {                 num += 1;                 msg = string.Format("線程 [{0}],實例[{1}]中num的值是[{2}]", Thread.CurrentThread.Name, this.Name, num);                 OnMessage(new MyEventArgs(msg));                 Thread.Sleep(100);             }             msg = string.Format("======線程 [{0}]執行完畢======", Thread.CurrentThread.Name);             OnMessage(new MyEventArgs(msg));         }     } 復制代碼 測試用的類寫完了,開始測試:   首先測試單個實例、多線程,2種鎖的區別:   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private void button1_Click(object sender, EventArgs e) {     LockTest test = new LockTest("LockTest 1");     test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);     listBox1.Items.Clear();     for (int i = 0; i <= 2; i++)     {         Thread a = new Thread(new ThreadStart(test.AddNum1));         a.Name = i.ToString();         a.Start();     } }   private void button2_Click(object sender, EventArgs e) {     LockTest test = new LockTest("LockTest 1");     test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);     listBox1.Items.Clear();     for (int i = 0; i <= 2; i++)     {         Thread a = new Thread(new ThreadStart(test.AddNum2));         a.Name = i.ToString();         a.Start();     } }   輸出結果一模一樣:       得出結論:如果對一個實例,多線程訪問的時候,2種鎖是沒有區別的。   下面是測試多個實例的情況(靜態鎖):   復制代碼         private void button3_Click(object sender, EventArgs e)         {             listBox1.Items.Clear();             for (int i = 0; i <= 2; i++)             {                 LockTest test = new LockTest("LockTest " + i.ToString());                 test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);                 Thread a = new Thread(new ThreadStart(test.AddNum1));                 a.Name = i.ToString();                 a.Start();             }         } 復制代碼 得到結果:     得出結論,在靜態鎖面前,線程依舊要排隊,雖然不是一個實例,但是鎖是唯一的,線程只認鎖,所以線程並沒有並發!   繼續測試(非靜態的鎖):   復制代碼         private void button4_Click(object sender, EventArgs e)         {             listBox1.Items.Clear();             for (int i = 0; i <= 2; i++)             {                 LockTest test = new LockTest("LockTest " + i.ToString());                 test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);                 Thread a = new Thread(new ThreadStart(test.AddNum2));                 a.Name = i.ToString();                 a.Start();             }         } 復制代碼 得到的結果:     得出結論:非靜態鎖的時候,多線程並發了,一起在工作。       其實,測試的結果之前也能猜想出來,只不過,不測試下,心裡總是覺得沒底,呵呵,測試完了,也就徹底釋然了!       窗體中,用於事件回調,顯示到UI裡的代碼在這裡:   復制代碼 delegate void MessageHandler(string msg);         public void MessageCallBack(object sender, MyEventArgs e)         {             MessageHandler handler = new MessageHandler(ShowMessage);             this.Invoke(handler, new object[] { e.Message });         }           public void ShowMessage(string msg)         {             this.listBox1.Items.Add(msg);         }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved