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

本文介绍了一个使用异步调用避免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;
        }
    }
}

 

 

转载于:https://www.cnblogs.com/flaaash/archive/2011/03/09/1978462.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值