首先讓我們體驗一下頻繁操作:
1)打開項目,在后台aspx.cs等服務器頁面,設置斷點.
2)點擊頁面按鈕
3)調試開始進入斷點,然后重復點擊頁面按鈕
4)服務器第一次事件已經處理完畢,調試再次進入了斷點,然后再進行處理
然后就出現了多條數據的新增問題.
使用lock也將無法解決該問題.因為lock是解決並發問題的,不是解決頻繁操作的問題的.
因此這里我要說一下並發操作和頻繁操作.並發是多個線程同時進行操作,頻繁操作是指一個操作未響應到客戶端,另一個操作再次重復進行,它們是2個不同的概念.
並發問題處理方法
大家可能很熟悉這個代碼:
public class Singleton { private volatile static Singleton _instance = null; private static readonly object lockHelper = new object(); private Singleton(){} public static Singleton CreateInstance() { if(_instance == null) { lock(lockHelper) { if(_instance == null) _instance = new Singleton(); } } return _instance; } }
對於並發,我們主要做的事情是:讓一個線程跑完之后再跑另一個線程,因此需要加鎖
加鎖使用了lock關鍵字,lock就是把{}中的代碼段鎖定,防止多個線程同時運行該代碼段.
我們一般對於普通並發,使用lock就可以解決了,但是如果是秒殺的這種情況呢。
我們這時候需要使用隊列集合去進行操作.
頻繁操作處理方法:
我們想象一下:第一次點擊按鈕,假設生成了一個操作會話OperSA1,服務器執行第一次按鈕操作的事件,執行未完成時,再次點擊該按鈕,
生成第2個操作會話OperSA2,服務器操作等待中.第一次按鈕事件操作完成之后,客戶端還沒有響應這時候服務器就忙着執行第2次按鈕事件了。
我們認為服務器執行操作是有錯的,錯在第1次按鈕事件執行完成之后沒有立即響應給客戶端就執行第2次操作了。可是服務器認為它本身是沒有錯的。
它認為錯的是客戶端,客戶端操作頻繁了。這時候怎么辦呢?
我們不如給服務器和客戶端定一個操作約定:
在客戶端定義一個會話標識符OperFrequent,如果客戶端執行了第一次操作,則會話標識符OperFrequent生成標識,如果客戶端再次執行了操作,但是會話標識符標識已經生成,則終止該操作。這是客戶端的約定。
服務器在接到請求后,執行操作,操作完成后,清理客戶端標識符。這是服務器的約定。
所以服務器必須在實際響應客戶端之后才能修改客戶端的會話標識符。
代碼:
會話標識符定義:
responseVal就是OperFrequent
<input type="hidden" id="responseVal" value="none" runat="server" />
客戶端執行操作:
if (document.getElementById('responseVal').value == 'none') { document.getElementById('responseVal').value = 'change'; // 觸發服務器事件 }
服務器響應操作:
this.responseVal.Value = "none";