static变量与asp.net


(copy from Meyer's bolg )

在C#中,static变量表示该变量属于类,而不是类的实例。可以说是该类的所有实例共享一个static变量。

asp.net的页面就是一个类,我们访问一个页面。就会在服务器上实例化一个该类的实例,来响应我们的请求。


“所有实例共享一个static变量” 这就意味着,所有的客户端访问到的asp.net页面中static变量都是同一个变量。

由于我们每次访问asp.net页面都是一个全新的对象,而不是我们上一次访问的对象。所以上次页面访问时我们对页面中变量的改动都没有保留。遇到这个问题的时候,很多初学者的直觉就是将这个变量申明为static,自己在测试的时候发现还真的保留住了页面的状态。窃喜之余没有发现这又有引入了另外一个错误。因为你要的只是页面能保留住状态,而这个状态是针对一个客户端的(session的效果)。而得到的结果是只要一个客户端改变了该值所有的其他客户端都受到了影响(如同Applicatin的效果)。这种情况下,需要的极有可能就是个ViewState或者是Session。

Application与static变量

Application是通过一个集合保存所有的对象。

强类型:

Application中保存的是object,对对象的保存和使用需要作cast动作。对于值类型更需要Box&UnBox。对性能的影响较大。

而static变量是强类型的对象。

线程同步:

Application将所有的对象放到一个集合,这样对访问集合中的任何对象都会锁定这个集合。

假如有Application["A"]、Application["B"]、Application["C"],有线程访问Application["A"]其他线程不能访问Application["B"] and Application["C"]。

而static变量,可以根据他们的作用分别放在不同的class当中。这样可以并行访问不同的static变量,而不存在线程安全问题。

友情提示:

1. 对static变量,做lock时。可以通过lock(typeof(classname))来锁定该变量所在的类的类型,达到线程同步的目的。

2. 由于Aplication,static member是全局变量,而我们是在多线程服务器环境写程序,对他们的使用需要注意线程安全的问题。



ASP.Net状态管理

Asp.Net提供了四种状态类型:application,session,cookie,view。

Application状态为应用程序提供了一个全局的状态。所有客户都可以使用该状态。从设计的角度来说,我们通常用Application来存储一些标准的数据。同时,我们在使用它时要注意避免性能的降低,存储的数据尽可能提供给客户只读的功能。

我们可以使用HttpApplication类的Application属性来访问Application状态,它返回一个HttpApplicationState类的实例。这个类是一个对象集合,可以存储任何类型的数据,并以键/值对的形式存储。一旦数据被存储到状态后,就不会删除,除非应用程序重新启动或者被终止或回收。

我们可以在Global.asax的Application_Start函数中存储数据:

void Application_Start(object src, EventArgs e)

{

int exp = 0;

// population of dataset from ADO.NET query not shown

// Cache DataSet reference

Application["Experiment"] = exp;

}

现在你可以在任意页面下使用它:

private void Page_Load(object src, EventArgs e)

{

  int expr = Int32.Parse((Application["Experiment"]));

}

由于Application状态对于所有客户都是共享的,如果客户只是读取该数据,则没有什么问题,一旦要进行写操作,就不能保证线程的安全以及出现同步争用的问题。我们可以使用HttpApplicationStateLock类,它派生于ReadWriteObjectLock类,它提供了读/写锁的两种属性。在ASP.Net下,隐式地调用了AcquireWrite()和AcquireRead()方法以保证避免上面的问题。当然,我们也可以显示地使用Lock()和Unlock():

private void Page_Load(object sender, System.EventArgs e)

{

 Application.Lock();

 int expr = Int32.Parse((Application["Experiment"]));

 if (expr>=something)

 {

  //do something

 }

 Else

 {

  //do something else

 }

 Application.UnLock();

 //Some other thing goes here

}

session,cookie,view状态都是用来保存客户端信息的。它们之间又有什么区别呢?

Session状态是在客户登录的时候创建的,它保存了客户特定的信息,并以Session ID来标识。当一个新客户访问应用程序时,先生成一个新的Session ID(或是Session Key),并为同一个客户接下来的请求创建联系。你可以在Session State中存储任意类型的数据,作为你的应用,状态被同一个进程和AppDomain(App域)维护。Session State的特点是为每一个特定的客户创建状态以维护客户的信息,这些状态信息存储在服务器端的默认的会话状态配置中。

Session(“Value”) = expr ; // Storing the data into session object

SomeFunction()

{

 int expr = Int32.Parse(Session(“Value”));//Accessing from it

 if (expr>=something)

 {

  //do something

 }

 Else

 {

  //do something else

 }

  //Some other thing goes here

}

既然Session State针对特定的客户建立,通过它来识别客户的请求。Asp.Net提供了一种加密机制和编码算法生成自己的Session Key。这是非常必要的,因为知道了你的Session Key,就有权限访问指定的页面了。

在ASP.Net中生成Session Key的方法:

byte[] sessionkey = new byte[15];

//Generates a random number

RNGCryptoServiceProvider rngkey = new RNGCryptoServiceProvider ();

rngkey.GetBytes (sessionkey);

string clientsessionKey = SessionId.Encode (sessionkey);

但是Session和客户端的Cookie是有关的,当客户关掉Cookie时,Session就失效了。不过在ASP.Net

中可以在web.config中修改设置,使Session的传递脱离Cookie。方法是:

<configuration>

  <system.web>   

    <sessionState cookieless="true" />

  </system.web>

</configuration>

对于Cookie大家并不陌生,每个Cookie存储了多个名/值对,我们可以通过HttpCookie类的值集合来访问它,也可以间接地通过类所提供的索引器访问。Cookie在ASP.Net下的使用:

protected void Page_Load(Object sender, EventArgs E)

{

 int expr = 0;

 if (Request.Cookies["Expr"] == null)

 {

  // "Expr" cookie not set, set with this response

  HttpCookie cokExpr = new HttpCookie("Expr");

  cokExpr.Value = exprTextBox.Text;

  Response.Cookies.Add(cokExpr);

  expr = Convert.ToInt32(exprTextBox.Text);

 }

 else

 {

  // use existing cookie value...

  expr = Convert.ToInt32(Request.Cookies["Expr"].Value);

 }

 // use expr to customize page

}

由于Cookie存储的信息是放到客户端的,用户在访问服务器端页面时,必然在客户端和服务器端之间频繁交换信息,影响了程序的性能。而Session由于存储在服务器内存中,因此不存在这个问题。不过,Session存储的信息是临时的,用户一旦关闭浏览器,状态即失去。而Cookie则相反。

至于View State,主要是指控件和页面的状态信息,它以_VIEWSTATE值传递给服务器端。​

Application、Session和Cookie,可以借用Carfield的总结:

COOKIE 是本地文件,是 40 大盗在阿里巴巴家做的记号,或者是送牛奶的人在你家门口钉的箱子。

SESSION 是服务器端内存,是你洗澡时浴池发给你的钥匙。自己专用,可以开自己的好多箱子。

APPLICATION 是公共浴池。在这里能看见所有人,包括 ppmm 哦:)。