许明会的计算机技术主页

Language:C,C++,.NET Framework(C#)
Thinking:Design Pattern,Algorithm,WPF,Windows Internals
Database:SQLServer,Oracle,MySQL,PostSQL
IT:MCITP,Exchange,Lync,Virtualization,CCNP

导航

大容量数据传输UI无响应怎么办:异步查询大结果集!

数据库管理程序中,如果涉及大容量的数据传输,在数据检索过程中可能导致UI无响应。这里模拟这个过程,并通过异步调用避免UI停滞问题。
该示例有共有3个button和1个DataGridView控件,其中2个button用于分别正常检索数据和异步检索数据,另一个button用于绑定数据。
异步调用实际是开启新的非UI线程处理数据,因此异步调用中弹出的对话框也是和用户UI没关系的。程序中让数据访问延时5秒,尝试拖动窗体看看效果。


 

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

using System.Data.SqlClient;
using System.Collections;

namespace snippetWinForm
{
    
public partial class frmSnippet : Form
    {
        
public frmSnippet()
        {
            InitializeComponent();
        }

        
//Variable declaration
        string connectionString = "Data Source=.\\sqlexpress; Initial Catalog=Northwind; Integrated security=true;Asynchronous Processing=true";
        
string selectString = "waitfor delay  '0:0:5'; select productname, quantityPerUnit, unitPrice, unitsInStock, UnitsOnOrder from products;  ";
        ArrayList al 
= new ArrayList();

        
/// <summary>
        
/// 加载数据,并填充到ArrayList对象; 
        
/// 此为非异步调用,所以大容量数据时可能UI停止响应;
        
/// 如MessageBox弹出后绑定按钮无法按下。
        
/// </summary>
        private void btnLoad_Click(object sender, EventArgs e)
        {
            al.Clear();
            
using (SqlConnection  cn = new SqlConnection(connectionString))
            {
                SqlCommand  cmd 
= new SqlCommand(selectString, cn);
                cn.Open();

                SqlDataReader dr 
= cmd.ExecuteReader(CommandBehavior.CloseConnection);

                
if (dr.HasRows )
                {
                    
foreach (var item in dr)
                    {
                        al.Add(item);
                    }
                    dr.Close();
                }
                cn.Close();
            }
            MessageBox.Show(
"UI  Thread:Data Load finished, you can bind the data now!""Data Load");
        }


        
/// <summary>
        
/// 异步调用唤起,命令对象cmd执行完毕后执行异步回调AsyncCallback callback
        
/// </summary>
        private void btnLoadDataAsync_Click(object sender, EventArgs e)
        {
            al.Clear(); 
            SqlConnection  cn 
= new SqlConnection(connectionString);//此处若用using语句包括,将无法实现异步调用!!!
            {
                SqlCommand  cmd 
= new SqlCommand(selectString, cn);
                cn.Open();

                AsyncCallback callback 
= new AsyncCallback(DataReaderIsReady);
                IAsyncResult asyncResult 
= cmd.BeginExecuteReader(callback, cmd);
            }
        }


        
/// <summary>
        
/// 回调方法,在命令cmd执行完毕后调用该callback方法;
        
/// AsyncCallback callback = new AsyncCallback(DataReaderIsReady);
        
/// IAsyncResult asyncResult = cmd.BeginExecuteReader(callback, cmd);
        
/// </summary>
        
/// <param name="result"></param>
        private void DataReaderIsReady(IAsyncResult result)
        {
            
//因为是异步调用,所以这个MessageBox是非模式的对话框,可以继续点击UI。
            
//问题:在MessageBox显示的时候点击绑定按钮(此时ArrayList为空),然后确定MessageBox,此时尽管ArrayList有数据,但也无法绑定,WHY?
            MessageBox.Show("Asynchronous callback ,None UI Thread : Result Load Complete!""I'm Done!");
            SqlCommand  cmd 
= (SqlCommand)result.AsyncState;
            SqlDataReader dr 
= cmd.EndExecuteReader(result);

            
if (dr.HasRows)
            {
                
foreach (var item in dr)
                {
                    al.Add(item);
                }
            }
            dr.Close();
            cmd.Connection.Dispose();

            
//btnBind.Enabled = true; //因为该方法在另外的非UI先线程里,所以对btnBind不可见!
        }        
        
        
/// <summary>
        
/// 只需要将DataGridView的DataSource指定为ArrayList对象,就完成了绑定。
        
/// </summary>
        private void btnBind_Click(object sender, EventArgs e)
        {
            dgvProducts.DataSource 
= al;
        }
    }
}

 

 

posted on 2011-03-09 16:19  许明会  阅读(677)  评论(0编辑  收藏  举报