Don't think you are, know you are

博客园 首页 新随笔 管理


当执行某些需要花费很长时间才能完成的数据库操作时,往往需要设置设计异步的处理的方法,以避免用户长期得不到响应,导致程序假死。在ADO.Net 2.0中,其SqlCommand类也提供了一组Begin~和End~的Execute方法对,用于执行异步操作,通过这些方法对,用户可以轻松地实现异步操作,而不需要掌握过多的线程开发技术细节。比如ExecuteNonQuery 相应的异步方法为 BeginExecuteNonQuery,EndExecuteNonQuery。

同步与异步方法在调用上的差异在于:同步方法执行后,会阻塞处理进程,直接返回处理结果,而异步执行方法通过Begin~方法启动执行处理,然后将处理权交给调用者,调用者可以做别的事情,如果要取得异步执行的结果,需要调用End~方法,否则结果会丢失。

在异步执行处理中,主要需要考虑的是在异步执行开始后(通过Begin~方法的调用),如果获取异步执行的状态,以便在需要的时候,通过End~方法取回异步执行的结果。每个IAsyncResult接口对象,如果需要知道Begin~方法执行的状态,可以查询IAsyncResult接口对象的IsCompleted属性。当该属性返回True时,表示异步方法执行完成,可以调用与之对应的End~方法获取执行结果。 如果在异步执行完成前调用~End方法,则~End方法会等待,阻塞主线程,直到异步方法执行完成并返回结果。比较常用的另一种方法是:在调用Begin~方法开始异步执行时,传入委托实例。Begin~有几个重载,其中有2个可以传入委托实例,由执行异步方法的工作线程通过委托自动回调制定的回调函数。下面这个例子说明了这种方法。



如图建立Windows程序,下方是一TabPage控件。代码如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace queryCallBackDemo
{
    public partial class Form1 : Form
    {
        private Int32 m_runningCount = 0;
        private string m_ConnStr = "Data Source=xiaoxiao\\SQLEXPRESS;Initial Catalog=tempdb;Integrated Security=True;Asynchronous Processing=true";
        private SqlConnection getConnection()
        {
            SqlConnection iRe = new SqlConnection(this.m_ConnStr);
            iRe.Open();
            return iRe;
        }


        private delegate void addNewTabPageDelegate(TabPage sTabPage);

        private void addNewTabPage(TabPage sTabPage)
        {
            this.tabControl1.TabPages.Add(sTabPage);

        }

        private void handleCallBack(IAsyncResult iResult)
        {
            try
            {
                using (SqlCommand iCmd = iResult.AsyncState as SqlCommand)
                {
                    TabPage iTabPage = new TabPage(iCmd.CommandText);
                    DataGridView iDataGridView = new DataGridView();
                    iDataGridView.Parent = iTabPage;
                    iDataGridView.Dock = DockStyle.Fill;
                    using (DataTable iDatatable = new DataTable())
                    {
                        iDatatable.Load(iCmd.EndExecuteReader(iResult));
                        iDataGridView.DataSource = iDatatable;

                    }
                    this.Invoke(new addNewTabPageDelegate(this.addNewTabPage), iTabPage);

                  //  this.tabControl1.TabPages.Add(iTabPage);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.m_runningCount -= 1;
            }

        }


        private void asyncExecuteQuery(string sSQL)
        {
            SqlCommand iCmd;
            try
            {
                iCmd = new SqlCommand(sSQL, getConnection());
                iCmd.BeginExecuteReader(new AsyncCallback(this.handleCallBack), iCmd);
                this.m_runningCount += 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }


        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.m_runningCount > 0)
            {
                MessageBox.Show(m_runningCount.ToString() + "  query are still running, please wait");
                e.Cancel = true;
            }
        }

        private void btnDoquery_Click(object sender, EventArgs e)
        {
            string iSQL = this.textBox1.Text.Trim();
            if (!string.IsNullOrEmpty(iSQL))
                this.asyncExecuteQuery(iSQL);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            if (this.m_runningCount > 0)
                MessageBox.Show(m_runningCount.ToString() + "  query are still running, please wait");
            else
                this.tabControl1.TabPages.Clear();
        }
    }
}

 

 

 


几个注意:连接串加上 Asynchronous Processing=true 。

iCmd.BeginExecuteReader(new AsyncCallback(this.handleCallBack), iCmd);  开始异步委托调用,
SqlCommand iCmd = iResult.AsyncState as SqlCommand 获取传入的ICmd

异步调用中不能直接   this.tabControl1.TabPages.Add(iTabPage);
因为tabControl1.是在另一个线程中创建的,而要使用  this.Invoke(new addNewTabPageDelegate(this.addNewTabPage), iTabPage);

 

 

posted on 2008-05-09 17:07  炭炭  阅读(1409)  评论(0编辑  收藏  举报