首先讓咱們體驗一下頻繁操做:服務器
1)打開項目,在後臺aspx.cs等服務器頁面,設置斷點.併發
2)點擊頁面按鈕this
3)調試開始進入斷點,而後重複點擊頁面按鈕spa
4)服務器第一次事件已經處理完畢,調試再次進入了斷點,而後再進行處理線程
而後就出現了多條數據的新增問題.調試
使用lock也將沒法解決該問題.由於lock是解決併發問題的,不是解決頻繁操做的問題的.code
所以這裏我要說一下併發操做和頻繁操做.併發是多個線程同時進行操做,頻繁操做是指一個操做未響應到客戶端,另外一個操做再次重複進行,它們是2個不一樣的概念.server
併發問題處理方法blog
你們可能很熟悉這個代碼:隊列
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";