今天在做程序測試的過程中,發現程序出現只要一個客戶端訪問程序,其他客戶端訪問都受到影響。
后來一查是在程序中設了靜態變量的關系,由于靜態變量是全局的所以會出錯。
對此問題進行學習一下(下列內容來自各個網頁精華,由于截取不同網頁,如有侵權,請和我聯系):
利用asp.net 開發基于B/S模式的應用系統,經常會遇到同一頁面類的各函數成員之間、 同一會話各頁面之間、不同機器各用戶頁面之間的傳值問題,即要解決數據共享的問題。這可以選擇使用Application、Session、cookie、Static、ViewState 等方法實現。
其中Static變量的使用容易出現問題,使用不好會導致數據紊亂,給系統造成故障隱患。
用ViewState 作為頁內數據傳值也是一種較好的選擇 。
在C#中,static變量表示該變量屬于類,而不是類的實例。可以說是該類的所有實例共享一個static變量。
asp.net的頁面就是一個類,我們訪問一個頁面。就會在服務器上實例化一個該類的實例,來響應我們的請求。
“所有實例共享一個static變量” 這就意味著,所有的客戶端訪問到的asp.net頁面中static變量都是同一個變量。
由于我們每次訪問asp.net頁面都是一個全新的對象,而不是我們上一次訪問的對象。所以上次頁面訪問時我們對頁面中變量的改動都沒有保留。
遇到這個問題的時候,很多初學者的直覺就是將這個變量申明為static,自己在測試的時候發現還真的保留住了頁面的狀態。竊喜之余沒有發現這又有引入了另外一個錯誤。因為你要的只是頁面能保留住狀態,而這個狀態是針對一個客戶端的(session的效果)。而得到的結果是只要一個客戶端改變了該值所有的其他客戶端都受到了影響(如同Applicatin的效果)。
究其原因這還要從Asp.net的運行機制談起。在C/S模式軟件開發過程中,我們通常不會關心應用程序是在哪里運行的,變量存放在哪里,客戶端程序就運行在客戶端,服務器端程序就運行在服務器端,一般情況下,二者除了數據庫中的數據外基本沒有其他共享的問題。 所以這時客戶端的用戶大可放心的使用static變量,因為它們就存放在客戶端程序中。
于是我們就習慣的在做B/S模式的頁面時也用static變量,殊不知Asp.net中的static已 不同于C/S中的static。是因為在Asp.net中所有的用戶將使用同一個static變量。這就意味 著每一個使用該頁面的用戶對該變量的操作將會影響到其他用戶。
解決的辦法之一是可以選擇Asp.net提供的ViewState對象。ViewState對象可以用來保存頁面中的各種變量,甚至是對象。“有些數據可以直接保存到ViewState中,諸如字符串 、整數、布爾、數組里表、哈希表等。”
“所謂ViewState,實際上是一些鍵值對,ASP.NET通過它維護網頁和服務器的狀態,并將ViewState封裝成一個或幾個隱藏的表單域傳遞到客戶端。而客戶端提交時,ViewState也 將被提交到服務器端。這樣后續的請求可以獲得上一次請求的狀態。”
只要用變量名稱做索引,如ViewState[“Var ”], 就可以存取變量Var的值,而不管Var是普通變量,還是對象,甚至是內存中的一張DataTabl e。服務器端會為每個連接到該頁面的用戶分別建立一個ViewState,所以ViewState相當于 頁面級的Session。相當于頁面全局變量,但是一旦退出當前頁面,它就會丟失。
ViewState的用法很簡單,如下所示:
1、保存變量到ViewState中(賦值):
ViewState[“times”]=times; //存放普通變量times
ViewState[“Orders”]=dtOrders; //存放DataTable型對象dtOrders
ViewState ["aa"] ="123";
2、讀出ViewState中的值(取值):
times = (int)ViewState[“times”];
dtOrders = (DataTable)ViewState[“Orders”];
string bb = ViewState["aa"].ToString();
讀出變量的值時要進行強制類型轉換,這是因為當變量(不管是int型的普通變量times ,還是DataTable型的對象dtOrders)被存放到ViewState中后統統按Object類型存放。所以 當我們從ViewState取出時,一定要轉換成相應的類型,否則就會報錯。在變量保存到ViewS tate中時,系統會自動轉換。
這不是說static型變量就沒用了,在C#中用static聲明的類不用實例化直接使用。正是由于所有用戶共享服務器端的同一個static變量,所以可以用static型對象來存取一些公用的處理模塊,比如類型轉換、變量驗證等工作。所以要根據具體情況而定。
還有一點需要注意:如果在頁面中多個過程要共享一個對象或變量,我們在頁面類的開始部分定義一個頁面級的全局變量是不行的,static本來可以,但上面說了這種類型的變量不安全,所以這時就可以用ViewState。
ViewState是將數據存入到頁面隱藏控件里,不再占用服務器資源,因此, 我們可以將一 些需要服務器"記住"的變量和對象保存到viewstate里面。viewstate并不能存儲所有的.net 類型數據,它僅僅支持String、Integer、Boolean、Array、ArrayList、Hashtable 以及自定義的一些類型。
ViewState 常用于保存單個用戶的狀態信息,生存期等于頁面的生存期。viewstate是 在本頁面之內各函數間進行傳值的 , 至于為什么要使用這種方法是因為在一個事件發生之后 , 頁面可能會刷新 , 如果定義全局變量會被清零 , 所以要使用 viewstate保持數據,任何事物都有兩面性, 因為ViewState變量在客戶端實際上是用<input type=“hidden ” value=“ADFAIB3P234P-AFAFAF……”/>保存的一個對象,這樣如果要保存的是個對象, 甚 至是個很復雜的對象(如DataTable),這樣以來就會增加網絡傳輸的負擔。 使用viewstat e會增加頁面html的輸出量,占用更多的帶寬,這一點是需要慎重考慮的。另外, 由于所有的v iewstate都是存儲在一個隱藏域里面,用戶可以很容易的通過查看源碼來看到這個經過base6 4編碼的值,然后再經過轉換就可以獲取你存儲其中的對象和變量值。
ViewState只能在一個頁面上傳值(session可跨多個頁面傳值),ViewState只是在當前page內有效,關了當前頁,再重新打開,ViewState所保存的值也就消失了。需要在用戶訪問一個頁面時保持一個變量的值,并隨時改變它的值,用ViewState好些。ViewState是用來同步客戶端與服務端的變量狀態的!當有兩個用戶對同一頁面進行操作時,若使用Static出現了數據張冠李戴的嚴重錯誤時,改為ViewState后就會一切正常了。
開發C/S模式的系統和開發B/S模式的系統有很大的不同。因此我們一定要根據不同情況正確理解各種變量的作用域和生存期,以便能夠正確使用各種保存數據的方法而不至于出現 錯誤。
posted on 2011-09-06 10:07
墻頭草 閱讀(272)
評論(0) 編輯 收藏