伊莉討論區
標題:
C#中 lock的使用?
[打印本頁]
作者:
ggnnyy
時間:
2017-10-12 10:15 AM
標題:
C#中 lock的使用?
本帖最後由 ggnnyy 於 2017-10-12 10:25 AM 編輯
各位大大好:
最近在研究訂單系統的取號機制,在多人使用的環境下訂單編號能夠不被重複取用...
上網有搜尋到許多方法,但有人提到用如下方法,我查了一下lock的鎖定好像是針對程式碼區塊的鎖定,
所以訂單系統如果是網站型態的應該是可以鎖定,但是如果是winform的型態呢? 這樣lock能達到鎖定不讓多個使用者存取到一樣的單號嗎?
private void LockInsert(object i)
{
lock (thisLock)
{
using (SqlConnection myConnection = new SqlConnection(SqlDataSource1.ConnectionString))
{
SqlCommand myCommand = new SqlCommand();
myCommand.Connection = myConnection;
myCommand.CommandText = "Insert Product (ProNo,ProName) values (@ProNo,@ProName)";
myCommand.Parameters.AddWithValue("@ProNo", GetProductSerialNumber());
myCommand.Parameters.AddWithValue("@ProName", "Product_" + i);
myConnection.Open();
myCommand.ExecuteNonQuery();
}
}
}
複製代碼
作者:
sam30525sam
時間:
2017-10-12 10:20 PM
本帖最後由 sam30525sam 於 2017-10-12 10:21 PM 編輯
lock不管你是 asp.net mvc 或 asp.net web api 或 webform都可以使用,這樣講好了,
不管你是應用程式還是網頁,其實核心都一樣,
但是要注意的點差蠻多就是了。
依照你的程式碼的話,你這個lock永遠都沒有用,
因為網頁每一次request近來,都會產生一個新的instance,
而且你又寫lock(this),這種最耗效能的東西,
整體看起來有點悲劇。
如果你要寫lock,我建議你參考以下看看
1. 要注意,所謂的lock就是「場上只有一個旗子,誰拿到,誰就可以做動作」
所以回過頭看你的程式碼,你就會發現instance會產生很多「同名稱,但不一樣的旗子」,
那如何才可以產生只有一個旗子呢?
那你就用static就好了。
2. lock是鎖什麼,就是鎖記憶體
看到一推新手常常寫lock(this),這代表是說,我要lock這整個class的instance,
這樣子就像是,
「我只是要拿一杯水,但是我要求全公司的人都不能動,我拿了水之後,你們才可以繼續」
但其他公司的人也許只是要列印文件,為什麼你拿水,明明沒關係,卻還要等你做完?
建議你根據該相對應的行為,建立相對應的「鎖」就好。
請參考以下範例
public static class LockExample
{
/// <summary>會員列表</summary>
private static List<string> _MemberList;
/// <summary>會員列表鎖</summary>
private static object _MemberListLocker;
/// <summary>歌曲列表</summary>
private static List<string> _SongList;
/// <summary>歌曲列表鎖</summary>
private static object _SongListLocker;
static LockExample()
{
LockExample._MemberList = new List<string>();
LockExample._MemberListLocker = new object();
LockExample._SongList = new List<string>();
LockExample._SongListLocker = new object();
}
public static string GetMember(int index)
{
lock (LockExample._MemberListLocker)
{
return LockExample._MemberList[index];
}
}
public static void AddMember(string newMember)
{
lock (LockExample._MemberListLocker)
{
LockExample._MemberList.Add(newMember);
}
}
public static string GetSong(int index)
{
lock (LockExample._SongListLocker)
{
return LockExample._SongList[index];
}
}
public static void AddSong(string newSong)
{
lock (LockExample._SongListLocker)
{
LockExample._SongList.Add(newSong);
}
}
}
複製代碼
作者:
ggnnyy
時間:
2017-10-12 11:39 PM
感謝SAM大~~~~~
可否在請問,如果是winform的形式(不是webform喔)
為什麼這種方式也能鎖定?
既然是鎖定程式碼區塊,winform每個用戶端不是都是獨立的個體嗎?
作者:
sam30525sam
時間:
2017-10-14 12:32 AM
ggnnyy 發表於 2017-10-12 11:39 PM
感謝SAM大~~~~~
可否在請問,如果是winform的形式(不是webform喔)
為什麼這種方式也能鎖定?
我的解法,winform/網頁程式都可以,
至於你說的winform每個用戶端都是獨立的個體,
這個你要定義你的client side是什麼,
我們通常定義client side就是一個應用程式,一個process。
但這個跟我所講的沒關係,
我所講的是class在實體化的時候,所配發的記憶體,
舉的例子來講,假設程式碼如下
public class Dog
{
public static int Hair { get; set; }
public int Size { get; set; }
}
複製代碼
Dog emily = new Dog();
Dog shary = new Dog();
複製代碼
emily的Size跟shary的Size是不同份記憶體,
所以你lock Size是沒用的。
但是emily的Hair跟shary的Hair是同一份記憶體,
你lock Hair就有用。
詳細的請你自己去看static 與instance的差異在哪裡
作者:
Jeepluo
時間:
2017-10-18 03:02 PM
如果只是要取訂單號碼,使用 Record Lock的方式並非是個好的方式,甚至是一個很不好的方法,取單號的方式有很多,就看你的單號顯示的重要性。
例如說:
如果只是要有一個單號做區分,可以在存檔時利用 Trigger功能在Insert時產生流水號。
如果要先看到單號,那就可以利用 SQL Transition 功能確認產生取得方式。
作者:
checkbox4
時間:
2017-12-29 02:19 AM
您需要的是database層次的lock 而不是程式碼的lock
序號或流水號問題 使用資料庫技術比較容易解決
作者:
sunneo
時間:
2018-1-21 03:14 AM
C#的lock的使用要小心喔
建議lock物件是object且不可以是會被修改的物件,
因為當你的物件內容變了,那個lock可能會失效,比方說當你lock的對象是list、或者可以被dispose的物件。
https://docs.microsoft.com/zh-tw ... ords/lock-statement
如果你不想要使用區塊式的lock語法,那麼你可以用Monitor.Enter,Monitor.Exit來確保程式操作是在一個Monitor操作區間
歡迎光臨 伊莉討論區 (http://www545675.eyny.com/)
Powered by Discuz!