同步和异步访问数据库

   我们都知道,某些场合下,在对数据库进行访问时,为了避免同步访问数据时所带来的延迟,我们需要改进设计,以提高程序执行效率。一方面,这可以给用户以良好的使用体验;另一方面,也降低了程序崩溃的可能性。为实现这一目的,我们采用异步方式来访问数据库。先看下面的代码

 

private void button2_Click(object sender, EventArgs e) 
       
{   

       
using (SqlConnection cn = new SqlConnection(cnSettings.ConnectionString))//新建连接 
              
               cn.Open(); 
               
//新建命令 
               using (SqlCommand cmd = cn.CreateCommand()) 
               

                   cmd.CommandText 
= "WaitFor Delay '00:00:15' Select @@Version"
                   ver 
= (string)cmd.ExecuteScalar(); 
               }
 
           }
 
           label1.Text 
= ver;

}


     这个例子非常简单,这是同步的例子,:首先建立一个连接,打开连接后,创建一个SqlCommand,并设置命令,最后将执行后的值给到label控件.可以看到,整个例子都是在一个线程内进行的,并没有涉及到其他的线程,再看一下下面的例子.

 

private void button2_Click(object sender, EventArgs e) 
       
{   
   
//新建联接 
           SqlConnection cn = new SqlConnection(cnSettings.ConnectionString); 
           cn.Open(); 
           
//新建命令 
           SqlCommand cmd = cn.CreateCommand(); 
           cmd.CommandText 
= "WaitFor Delay '00:00:15' Select @@Version"
           
//在另外一个线程运行reader,ProcessResult可以看做是另外一个线程 
           cmd.BeginExecuteReader(new AsyncCallback(ProcessResult), cmd);

}


可以看到,上面的代码就是异步读取数据库,实际上就是开启了另外的一个线程,下面为处理代码

 

public void ProcessResult(IAsyncResult ar) 
       

           SqlCommand cmd 
= (SqlCommand)ar.AsyncState; 
           
using (cmd.Connection) 
           

               
using (cmd) 
               

                   
string ver = null
                   SqlDataReader rdr 
= cmd.EndExecuteReader(ar); 
                   
if (rdr.Read()) 
                   

                       ver 
= (string)rdr[0]; 
                       label1.BeginInvoke(
new LabelHandler(UpdateLabel), ver); 
                   }
 
               }
 
           }
 
       }
 

下面是委托的代码

      

 //声明一个委托代理 
       public delegate void LabelHandler(string text); 

       
public void UpdateLabel(string text) 
       

           label1.Text 
= text; 
       }


  

     值得注意的是,在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。

posted @ 2008-07-13 00:45  GIS小能  阅读(5762)  评论(1)    收藏  举报