2007-01-08
TAG:.net

出现这种问题的基本都是在web.config中把seesion的模式设置成了Inproc,Inproc是缺省的设置.

seesion用一次就丢失的诡异原因是缘于ASP. NET的进程内会话会使因asp.net的服务进程aspnet_wp.exe(IIS5.0/IIS5.01上,IIS6.0上是w3wp.exe)的重新启动而丢失.

同时1分钟或短时间内seesion丢失是因为在ASP.NET中因为性能与安全方面的的需要,在某些特定的条件下就重新启动其服务进程了。

比如,我们上传文件时,有可能使ASP.NET的服务进程占用到web.config中指定的内存使用上限,这时ASP.NET服务进程就重启以便释放内存资源,等等原因.

解决办法:

采用StateServer或者SQLServer模式,如果你开发的系统数据库压力相对大的话,建议采用StateServer模式.

下面给出配置步骤:

1.启动服务“ASP.NET   State   Service” 控制面板-管理工具--服务 找到该服务开启即可.   
 2.然后,修改web.config:  
          <sessionState    
                          mode="StateServer"  
                          stateConnectionString="tcpip=127.0.0.1:42424"  
                          sqlConnectionString="data   source=127.0.0.1;Trusted_Connection=yes"  
                          cookieless="false"    
                          timeout="140000"    
          />   
   





 
2006-12-28
TAG:.net

关于AjaxPro的性能改进
作者:Truly

偶然发现AjaxPro的页面注册是相当花费时间的方法

初步对AjaxPro方法进行分析,它的页面注册方法

AjaxPro.Utility.RegisterTypeForAjax(typeof(命名空间.类名));



是往页面上注册几段脚本块,






前3段是AjaxPro的内核函数,而最后一段则是我们页面上的Ajax方法封装集合。

事实上我们的网站是发布的站点,而这些Ajax方法基本上是写在业务层代码中的,所以发布之后并不需要经常修改。

注册2段Ajax方法集大约要花费300ms左右,这个花费是十分惊人的,所以我们不应该这样使用AjaxPro

AjaxPro的原理是当对“/ajaxpro/Space_For_Static,App_Web_gz3bdi8j.ashx”这样的路径请求时,生成指定类中Ajax方法集合,所以我们只需直接给页面增加这个脚本块地址即可。

要给页面增加这个块,有几种方法,使用<%= str %>,或者使用ClientScript.RegisterClientScriptBlock(.net 2.0)/RegisterClientScriptBlock(.net 1.x),但是根据我的测试,使用后者虽然比较简单而且安全,但是性能很差,所以推荐使用前者,同时我推荐另一种方法:

Literal l = new Literal();
l.Text = ""
  +  ""
  +  ""
  +  "";
Header.Controls.Add(l);



注意:以上代码适用于.Net 2.0

使用这个方法的好处是你不再需要修改.aspx,而且可以通过页面基类一次性给所以页面进行注册,性能非常好,大约15-30ms左右,这样性能至少提高了10倍!!

 

比如我在PageBase方法中定义了RegAjax方法:

public void RegAjax(Type type)
{
    // 用来代替 AjaxPro.Utility.RegisterTypeForAjax(Type type);方法
    string assemblyName = type.FullName + "," + type.
Assembly.FullName.Substring(0, type.Assembly.FullName.IndexOf(","));

    if (type.Assembly.FullName.StartsWith("App_Code."))
        assemblyName = type.FullName + ",App_Code";

    Literal l = new Literal();

    l.Text = "\n\n"
            + "\n"
            + "\n"
            + "\n";

    Header.Controls.Add(l);
}


然后我们在页面上使用

        RegAjax(typeof(Mythos.QianXun.BusinessRules.Notes));


来代替原始的

        AjaxPro.Utility.RegisterTypeForAjax(typeof(
Mythos.QianXun.BusinessRules.Notes));




 
2006-12-27
TAG:.net
抖动分成了两种抖动:
1。 生成随机数,改变窗体左上角坐标,然后立即把窗体的坐上角坐标还原,继续循环。
2。 生成随机数,改变窗体左上角坐标,循环完毕之后,然后立即把窗体的坐上角坐标还原。

核心代码如下:
//第一种抖动
        private void button1_Click(object sender, EventArgs e)
        
{
            
int recordx = this.Left;            //保存原来窗体的左上角的x坐标
            int recordy = this.Top;             //保存原来窗体的左上角的y坐标

            Random random 
= new Random();       

            
for (int i = 0; i < 100; i++)
            
{
                
int x = random.Next(rand);
                
int y = random.Next(rand);
                
if (x % 2 == 0)
                
{
                    
this.Left = this.Left + x;
                }

                
else
                
{
                    
this.Left = this.Left - x;
                }

                
if (y % 2 == 0)
                
{
                    
this.Top = this.Top + y;
                }

                
else
                
{
                    
this.Top = this.Top - y;
                }


                
this.Left = recordx;            //还原原始窗体的左上角的x坐标
                this.Top = recordy;             //还原原始窗体的左上角的y坐标
            }

           
        }

 


        
//第二种抖动
        private void button2_Click(object sender, EventArgs e)
        
{
            
int recordx = this.Left;
            
int recordy = this.Top;
            Random random 
= new Random();
            
for (int i = 0; i < 50; i++)
            
{
                
int x = random.Next(rand);
                
int y = random.Next(rand);
                
if (x % 2 == 0)
                
{
                    
this.Left = this.Left + x;
                }

                
else
                
{
                    
this.Left = this.Left - x;
                }

                
if (y % 2 == 0)
                
{
                    
this.Top = this.Top + y;
                }

                
else
                
{
                    
this.Top = this.Top - y;
                }

                System.Threading.Thread.Sleep(
1);
            }

            
this.Left = recordx;
            
this.Top = recordy;
        }




 
2006-12-27
TAG:.net

using System;
namespace CSDesingPattern
{
 class Singleton
 {
  private static Singleton mInstance;
  private int x = 0;  
  private Singleton(){}
  public static Singleton GetObject()
  {
   if (mInstance == null)
    mInstance = new Singleton();
   return mInstance;
  } 
  public void SetX(int newVal)
  {
   x = newVal;
  }
  public int GetX()
  {
   return x;
  }
  static void Main(string[] args)
  {
  
   int val;
   Singleton s1 = Singleton.GetObject();
   Singleton s2 = Singleton.GetObject();
   Console.WriteLine("将Singleton对象中的X设置为10");  
   s1.SetX(10);
   val = s2.GetX();
   Console.WriteLine("使用第二个Singleton变量读取X的值 x={0}", val);
   Console.ReadLine();
  }
 }
}

  • 设计要求:

    定义静态成员(指示自身类)

    private static Singleton mInstance;

    定义静态创建函数:

    public static Singleton GetObject()
      {
       if (mInstance == null)
        mInstance = new Singleton();
       return mInstance;
      } 
    用处:保持一个或固定个数的实例:如Asp.Net里的Application




 
2006-12-27
TAG:.net
private void button1_Click(object sender, System.EventArgs e)
        {
            PasteData();
        }

        private void PasteData()
        {
            IDataObject iData = Clipboard.GetDataObject();

            // 探测数据是否是可以使用的格式
            if(iData.GetDataPresent(DataFormats.Text))
            {
                string str = (String)iData.GetData(DataFormats.Text);
                textBox1.Text = str;
            }
        }





 
2006-10-11
TAG:.net

开发voosay过程中,一半的精力是设计界面样式以及一些css,先拿dw做出一个静态效果页面,然后把需要动态的部分切分开加上<%=words%>之类,对于那些循环出来的部分,刚开始的时候就直接嵌套到程序里去。

后来越做越恐惧,因为迟早界面要根据xujia的UI来重新设计的,到时候我岂不是又要做重复性又烦躁的工作吗?所以在开发到中期时我就加入了模板引擎的概念,把html标记切分开来,做成模板文件,对于那些需要动态的部分设计成标签例如${userinfo:age,sex}$等等,这样做的好处是可以方便于样式显示层的快速更换,可以更大程度更细的实现缓存,一定程度上实现了 显示 逻辑 数据 三层的真正分离。

现在voosay大部分已经开发完毕,回过头来我思考了很多,对于web2.0交互频繁的网站模板引擎是否适合,一般情况下模板引擎应用在大型门户信息类网站更多一些,而对于web2.0站点数据都是在实时变化的,只有极少部分数据是需要缓存的,同时因为模板引擎的工作流程是需要读入模板文件 然后拼出来html 返回到客户端,可以想象速度并不会快的特别多。

就我个人理解只要是做web开发,你就免不了和界面样式打交道,和美工打交道,模板引擎有助于比较彻底的把界面和程序分离开,如果你是做大型门户级的网站建议你使用模板引擎。

对于asp.net程序员来说,模板引擎会让你处于两难的境地,对于那些复杂的界面控制,显然可视化的设置控件的属性要比拼装支离破碎的模板来的容易和简单,同时使用模板引擎你也要丧失使用服务器端控件的机会,(虽然连ms都认为 尽量少用服务器控件为好,但毕竟服务器端控件非常容易操作阿。)

当前可以供我们选择的有这些模板引擎 我研究了几个 看起来都还不错,最少比我的强很多,MonoRail,stringTemplate.net,Velocity,NVelocity.

如果你用asp.net开发 建议你用NVelocity和stringTemplate.net





 
2006-09-16
TAG:.net 正则表达式
常见的判断




 
2006-08-31
TAG:.net

线程池 And 线程池的使用(基于.net平台)

多线程编程





 
2006-08-28
TAG:.net

Jeffrey Richter

Microsoft 一直试图提高其平台与应用程序的性能。许多年前,Microsoft 研究了应用程序开发人员是如何使用线程的,以便看看能做些什么来提高他们的效用。这项研究有一个很重要的发现:开发人员经常创建新线程来执行一项任务,当该项任务完成时,线程终止。

这种模式在服务器应用程序中极其常见。客户端请求服务器,服务器创建一个线程来处理客户端的请求,然后当完成客户端的请求时,该服务器的线程终止。与进程相比较,创建和销毁线程的速度更快,使用的操作系统资源更少。但创建和销毁线程当然不是免费的。

要创建一个线程,需要分配和初始化一个内核对象,也需要分配和初始化线程的堆栈空间,而且 Windows® 为进程中的每个 DLL 发送一个 DLL_THREAD_ATTACH 通知,使磁盘中的页分配到内存中,从而执行代码。当线程终止时,给每个 DLL 都发送一个 DLL_THREAD_DETACH 通知,线程的堆栈空间被释放,内核对象亦被释放(如果其使用数达到 0)。因此,与创建和销毁线程相关的许多开销都和创建线程原本要执行的工作无关。

线程池的产生

这项研究结果促使 Microsoft 去实现线程池,线程池最早出现在 Windows 2000 中。当 Microsoft® .NET Framework 小组设计并构建公共语言运行库 (CLR) 时,他们决定就在 CLR 自身中实现线程池。这样,即使应用程序是在 Windows 2000 以前的 Windows 版本(例如 Windows 98)中运行,任何托管的应用程序也都能利用线程池。

当 CLR 初始化时,其线程池中不含有线程。当应用程序要创建线程来执行任务时,该应用程序应请求线程池线程来执行任务。线程池知道后将创建一个初始线程。该新线程经历的初始化和其他线程一样;但是任务完成后,该线程不会自行销毁。相反,它会以挂起状态返回线程池。如果应用程序再次向线程池发出请求,那么这个挂起的线程将激活并执行任务,而不会创建新线程。这节约了很多开销。只要线程池中应用程序任务的排队速度低于一个线程处理每项任务的速度,那么就可以反复重用同一线程,从而在应用程序生存期内节约大量开销。

那么,如果线程池中应用程序任务排队的速度超过一个线程处理任务的速度,则线程池将创建额外的线程。当然,创建新线程确实会产生额外开销,但应用程序在其生存期中很可能只请求几个线程来处理交给它的所有任务。因此,总体来说,通过使用线程池可以提高应用程序的性能。

现在您可能想知道,如果线程池包含许多线程而应用程序的工作负荷又在减少,将会发生什么事情。这种情况下,线程池包含几个长期挂起的线程,浪费着操作系统的资源。Microsoft 也考虑到了这个问题。当线程池线程自身挂起时,它等待 40 秒钟。如果 40 秒过去后线程无事可做,则该线程将激活并自行销毁,释放出它使用的全部操作系统资源(堆栈、内核对象,等等)。同时,激活并自行销毁线程可能并不影响应用程序的性能,因为应用程序做的事情毕竟不是太多,否则就会恢复执行该线程。顺便说一句,尽管我说线程池中的线程是在 40 秒内自行激活的,但实际上这个时间并没有验证并可以改变。

线程池的一个绝妙特性是:它是启发式的。如果您的应用程序需要执行很多任务,那么线程池将创建更多的线程。如果您的应用程序的工作负载逐渐减少,那么线程池线程将自行终止。线程池的算法确保它仅包含置于其上的工作负荷所需要的线程数!

因此,希望您现在已理解了线程池的基本概念,并明白了它所能提供的性能优势。现在我将给出一些代码来说明如何使用线程池。首先,您应该知道线程池可以提供四种功能:

异步调用方法

以一定的时间间隔调用方法

当单个内核对象得到信号通知时调用方法

当异步 I/O 请求结束时调用方法

前三种功能非常有用,我将在本专栏中加以说明。而应用程序开发人员很少使用第四种功能,因此在此我将不做说明;有可能在将来的专栏中讲到。

功能 1:异步调用方法

在您的应用程序中,如果有创建新线程来执行任务的代码,那么我建议您用命令线程池执行该任务的新代码来替换它。事实上,您通常会发现,让线程池执行任务比让一个新的专用线程来执行任务更容易。

要排队线程池任务,您可以使用 System.Threading 命名空间中定义的 ThreadPool 类。ThreadPool 类只提供静态方法,且不能构造它的实例。要让线程池线程异步调用方法,您的代码必须调用一个 ThreadPool 的重载 QueueUserWorkItem 方法,如下所示:

public static Boolean QueueUserWorkItem(WaitCallback wc, Object state);
public static Boolean QueueUserWorkItem(WaitCallback wc); 

这些方法将“工作项”(和可选状态数据)排队到线程池的线程中,并立即返回。工作项只是一种方法(由 wc 参数标识),它被调用并传递给单个参数,即状态(状态数据)。没有状态参数的 QueueUserWorkItem 版本将 null 传递给回调方法。最后,池中的某些线程将调用您的方法来处理该工作项。您编写的回调方法必须与 System.Threading.WaitCallback 委托类型相匹配,其定义如下:

public delegate void WaitCallback(Object state);

请注意,永远不要调用任何可以自己创建线程的方法;如果需要,CLR 的线程池将自动创建线程,如果可能还将重用现有的线程。另外,线程处理回调方法后不会立即销毁该线程;它将返回到线程池并准备处理队列中的其他工作项。使用 QueueUserWorkItem 会使您的应用程序更有效,因为您将不需要为每个客户端请求创建和销毁线程。

图 1 中的代码说明了如何让线程池异步调用一个方法。

功能 2:以一定的时间间隔调用方法

如果您的应用程序需要在某一时间执行某项任务,或者您的应用程序需要定期执行某些方法,那么使用线程池将是您的最佳选择。System.Threading 命名空间定义 Timer 类。当您构造 Timer 类的实例时,您是在告诉线程池您想在将来的某个特定时间回调自己的某个方法。Timer 类有四种构造函数:

public Timer(TimerCallback callback, Object state,
   Int32 dueTime, Int32 period);
public Timer(TimerCallback callback, Object state,
   UInt32 dueTime, UInt32 period);
public Timer(TimerCallback callback, Object state,
   Int64 dueTime, Int64 period);
public Timer(TimerCallback callback, Object state,
   Timespan dueTime, TimeSpan period); 

所有这四种构造函数构造完全相同的 Timer 对象。回调参数标识您想由线程池线程回调的方法。当然,您编写的回调方法必须与 System.Threading.TimerCallback 委托类型相匹配,其定义如下:

public delegate void TimerCallback(Object state);

构造函数的状态参数允许您将状态数据传递给回调方法;如果没有要传递的状态数据,您可以传递 null。使用 dueTime 参数可以告诉线程池在第一次调用您的回调方法之前需要等待多少毫秒。可以利用一个有符号或无符号的 32 位值、一个有符号的 64 位值,或者一个 TimeSpan 值来指定毫秒数。如果您想立即调用回调方法,那么请将 dueTime 参数指定为 0。最后一个参数 period 允许您指定在每次连续调用之前需要等待的时间,单位为毫秒。如果您将 0 传递给这个参数,那么线程池将仅调用该回调方法一次。

构造 Timer 对象后,线程池知道要做什么,并自动为您监视时间。然而,Timer 类还提供了几种其他的方法,允许您与线程池进行通信,以便更改什么时候(或者是否)应当回调方法。具体地说,Timer 类提供了几种 Change 和 Dispose 方法:

public Boolean Change(Int32    dueTime, Int32    period);
public Boolean Change(UInt32   dueTime, UInt32   period);
public Boolean Change(Int64    dueTime, Int64    period);
public Boolean Change(TimeSpan dueTime, TimeSpan period); 
public Boolean Dispose();
public Boolean Dispose(WaitHandle notifyObject); 

Change 方法允许您更改 Timer 对象的 dueTime 和 period。Dispose 方法允许您在所有挂起的回调已经完成的时候,完全取消回调,并可选地用信号通知由 notifyObject 参数标识的内核对象。

图 2 中的代码说明如何让线程池线程立即调用一个方法,并且每隔 2000 毫秒(或两秒)再次调用。

功能 3:当单个内核对象得到信号通知时调用方法

Microsoft 研究人员在做性能研究时发现,许多应用程序生成线程,只是为了等待某单个内核对象得到信号通知。一旦该对象得到信号通知,这个线程就将某种通知发送给另一个线程,然后环回,等待该对象再次发出信号。有些开发人员编写的代码中甚至有几个线程,而每个线程都在等待一个对象。这是系统资源的巨大浪费。因此,如果当前您的应用程序中有多个线程在等待单个内核对象得到信号通知,那么线程池仍将是您提高应用程序性能的最佳资源。

要让线程池线程在内核对象得到信号通知时调用您的回调方法,您可以再次利用 System.Threading.ThreadPool 类中定义的一些静态方法。要让线程池线程在内核对象得到信号通知时调用方法,您的代码必须调用一个重载的 RegisterWaitHandle 方法,可以参见图 3

当您调用这些方法之一时,h 参数标识出您想要线程池等待的内核对象。由于该参数是抽象基类 System.Threading.WaitHandle,因此您可以指定从该基类派生出来的任何类。特别地,您可以将一个引用传递给 AutoResetEvent、ManualResetEvent 或 Mutex object。第二个参数 callback 标识出您想要线程池线程调用的方法。您实现的回调方法必须与 System.Threading.WaitOrTimerCallback 委托类型相匹配,其定义如下列代码行所示:

public delegate void WaitOrTimerCallback(Object state,
                                         Boolean timedOut);

第三个参数 state 允许您指定应传递给回调方法的某些状态数据,如果没有特别的状态数据要传递,则传递 null。第四个参数 milliseconds 允许您告诉线程池内核对象得到信号通知前应该等待的时间。这里通常传递 -1,以表示无限超时。如果最后一个参数 executeOnlyOnce 为真,那么线程池线程将仅执行回调方法一次。但是,如果 executeOnlyOnce 为假,那么线程池线程将在内核对象每次得到信号通知时执行回调方法。这对 AutoResetEvent 对象非常有用。

当调用回调方法时,会传递给它状态数据和 Boolean 值 timedOut。如果 timedOut 为假,则该方法知道它被调用的原因是内核对象得到信号通知。如果 timedOut 为真,则该方法知道它被调用的原因是内核对象在指定时间内没有得到信号通知。回调方法应该执行所有必需的操作。

在前面所示的原型中,您会注意到 RegisterWaitForSingleObject 方法返回一个 RegisteredWaitHandle 对象。该对象确定线程池在等待的内核对象。如果由于某种原因,您的应用程序要告诉线程池停止监视已注册的等待句柄,那么您的应用程序就可以调用 RegisteredWaitHandle 的 Unregister 方法:

public Boolean Unregister(WaitHandle waitObject);

waitObject 参数表明当执行完队列中的所有工作项后,您想如何得到信号通知。如果不想得到信号通知,那么您应将 null 传递给该参数。如果您将一个有效引用传递给 WaitHandle-derived 对象,那么线程池会在已注册等待句柄的所有挂起工作项执行完后,通知该对象。

图 4 中的代码说明如何让线程池线程在内核对象得到信号通知时调用方法。

小结

在本专栏中,我讲述了对线程池的需要,说明了如何利用 CLR 线程池提供的各种功能。现在您应该明白线程池为您的开发所带来的价值,它可以提高您的应用程序的性能,并简化您的代码。

您可以通过 dot-net@microsoft.com 将您的问题和建议发送给 Jeff

Jeffrey Richter 与他人共同创办了 Wintellect (http://www.Wintellect.com),该公司专门从事于 .NET 和 Windows 技术的培训、调试和咨询工作。他是 of Applied Microsoft .NET Framework Programming (Microsoft Press, 2002) 一书的作者,他还编写了几本有关 Windows 程序设计的书籍。

转到原英文页面





 
2006-08-23
TAG:.net

using System;
using System.IO;

//目录遍历

static public ArrayList  ListDirectory(string strFullPathName)
{
    DirectoryInfo dir = new DirectoryInfo(strFullPathName);

   ArrayList array = new ArrayList();
    DirectoryInfo[] dirSubs = dir.GetDirectories();//得到所有的目录

    //遍历子目录
    foreach(DirectoryInfo dirSub in dirSubs)
    {
        
        // 加进去目录名
        array.add(dirSub.FullName);

            }
return array;
    }


//获取目录中的文件方法

public ArrayList GetFielsInfo(string strFullPathName){

ArrayList array=new ArrayList();  

DirectoryInfo dir = new DirectoryInfo(strFullPathName);
    FileInfo[] files=dir.GetFiles();
    foreach(FileInfo file in files)
    {
        
        // 输出文件名
       array.add(file.Name);
    }

return array;
}





分页 共7页 第一页 上一页 1 2 3 4 5 6 7 下一页 最后一页
wwpizi@gmail.com
emir123456@hotmail.com
emir123456@yahoo.com.cn
我的档案:

访问统计: